Skip to content

Runtime Configuration

Plugin configurations are divided into compile-time and runtime configurations. Compile-time configurations are executed on the Node.js side, while runtime configurations are executed on the browser side.

Runtime configuration values can be of many types, including arrays, objects, functions, etc., and configurations can only be used after they are registered.

Configuration Method

By convention, plugin runtime configurations are used in the src/app.ts|tsx|js file. These configurations need to be exported through export for plugins to read and control Vue and Vue Router related configurations.

You can write functions, TSX, and import some dependencies here to complete certain configurations, but you can only import browser-side dependencies. Note that Node.js dependencies cannot be imported, otherwise it will cause infinite loops and abnormal situations. Also remember that imported dependencies should only be configuration-related. If you need to introduce global dependencies, please import them in the src/global.ts file.

TypeScript Support

If you want IntelliSense when writing configurations, you can define configurations using WinJS's defineApp method.

js
import { defineApp } from 'win';
export default defineApp({
  layout: () => {
    return {
      title: 'win',
    };
  },
});

// or
import { RuntimeConfig } from 'winjs';
export const layout: RuntimeConfig['layout'] = () => {
  return {
    title: 'win',
  };
};

Configuration Options

The following configuration options are sorted alphabetically.

modifyClientRenderOpts

modifyClientRenderOpts is a runtime plugin hook provided by WinJS for modifying render options before client-side rendering. Through this hook, when using Vue2, you can customize core instances such as router, store, pinia, etc., to achieve highly customized application initialization.

Basic Usage

Export the modifyClientRenderOpts function in src/app.js:

javascript
export function modifyClientRenderOpts(memo) {
  return {
    ...memo,
    // Add or modify render options here
  };
}

Parameters: memo Object

memo is the passed render options object, containing the following properties:

PropertyTypeDescription
routesIRoutesByIdWinJS route configuration object (key-value format)
routeComponentsIRouteComponentsRoute component mapping table
pluginManagerPluginManagerPlugin manager instance
rootElementHTMLElementMount root element
historyHistoryRoute history object (Vue Router 3.x is { base, mode })
basenamestringRoute base path
publicPathstringPublic resource path
runtimePublicPathbooleanWhether to use runtime public path
router >=0.16.6RouterCustom Vue Router instance. Provides higher flexibility and customization capabilities. This allows you to not follow WinJS routing conventions and adopt your original development mode, making it more convenient and faster to migrate projects to WinJS

Return Value

Returns a modified render options object that must include all original properties of memo.

Usage Scenarios

Scenario 1: Pass Custom Router Instance

Use Case: Need complete control over router instance, micro-frontend scenarios, using third-party routing libraries (Vue Router 3.x, Vue 2.x)

javascript
import customRouter from './router/index';

export function modifyClientRenderOpts(memo) {
  return {
    ...memo,
    router: customRouter
  };
}

Create custom router:

javascript
// src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import { routes } from './routes';

// Must register plugin first
Vue.use(Router);

const router = new Router({ 
  mode: 'hash', 
  routes,
  scrollBehavior(to, from, savedPosition) {
    return savedPosition || { x: 0, y: 0 };
  }
});

// Add global route guards
router.beforeEach((to, from, next) => {
  // Permission verification logic
  next();
});

export default router;
Scenario 2: Pass Vuex Store

Use Case: Using Vuex for state management (Vue 2.x)

javascript
import store from './stores';

export function modifyClientRenderOpts(memo) {
  return {
    ...memo,
    store: store
  };
}

Create Vuex store:

javascript
// src/stores/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    user: null,
    token: ''
  },
  mutations: {
    SET_USER(state, user) {
      state.user = user;
    },
    SET_TOKEN(state, token) {
      state.token = token;
    }
  },
  actions: {
    login({ commit }, { username, password }) {
      // Login logic
      return api.login({ username, password }).then(res => {
        commit('SET_USER', res.user);
        commit('SET_TOKEN', res.token);
      });
    }
  }
});
Scenario 3: Pass Pinia

Use Case: Using Pinia for state management (Vue 2.7+)

javascript
import { createPinia } from 'pinia';

export function modifyClientRenderOpts(memo) {
  return {
    ...memo,
    pinia: createPinia()
  };
}
Scenario 4: Pass Multiple Instances Simultaneously

Use Case: Need to customize both router and store

javascript
import customRouter from './router/index';
import store from './stores';

export function modifyClientRenderOpts(memo) {
  return {
    ...memo,
    router: customRouter,
    store: store
  };
}
Scenario 5: Modify Other Render Options

Use Case: Customize root element, modify base path, etc.

javascript
export function modifyClientRenderOpts(memo) {
  return {
    ...memo,
    // Customize root element
    rootElement: document.getElementById('app'),
    
    // Modify base path
    basename: '/my-app/',
    
    // Add custom properties
    customOption: 'custom-value'
  };
}

For example, dynamically modifying the render root node in micro-frontend:

js
let isSubApp = false;
export function modifyClientRenderOpts(opts) {
  return {
    ...opts,
    rootElement: isSubApp ? 'sub-root' : opts.rootElement,    
  };
}
javascript
export function modifyClientRenderOpts(memo) {
  return {
    ...memo,
    router: customRouter,
    store: store,
    pinia: createPinia()
  };
}

Advantages:

  • Clean and clear code
  • Complete type hints
  • Easy to understand and maintain

Compatible Approach (Via Callback)

javascript
export function modifyClientRenderOpts(memo) {
  const callback = () => {
    return {
      store: store,
      pinia: createPinia()
    };
  };
  return {
    ...memo,
    router: customRouter,
    callback
  };
}

onMounted({app, router})

Vue app mount success callback. Here you can get the app instance and router instance for global component registration, route guards, etc.

ts
export function onMounted({ app, router }: any) {
  console.log('onMounted', app, router);
  app.provide('win-hello', {
    h: 'hello',
    w: 'word',
  });
  
  // Route guards
  router.beforeEach((to, from, next) => {
    next();
  })
}

patchRoutes({ routes })

ts
export function patchRoutes({ routes, routeComponents }) {
  console.log('patchRoutes', routes, routeComponents);
}
  • routes: Flattened route list.

  • routeComponents: Route to component mapping.

render(oldRender: Function)

Overrides the render method.

For example, for permission verification before rendering:

bash
export function render(oldRender) {
  fetch('/api/auth').then(auth => {
    if (auth.isLogin) { oldRender() }
    else {
      location.href = '/login';
      oldRender()
    }
  });
}

router

Configure router settings:

ts
// src/app.tsx
export const router: RouterConfig = {
  // @ts-ignore
  scrollBehavior(to, from) {
    console.log('scrollBehavior', to, from);
  },
};

request

If you use import { request } from 'winjs'; to request data, you can customize middleware, interceptors, error handling adapters, etc., through this configuration. For details, refer to the request plugin configuration.

rootContainer(lastRootContainer, args)

Modifies the root component passed to Vue for rendering. The default is <router-view></router-view>.

  • lastRootContainer: The topmost root component.
  • args: Contains:
    • routes: Complete route configuration
    • plugin: Runtime plugin mechanism

For example, to wrap with a Provider:

js
import { h } from 'vue'

export function rootContainer(container) {
  return h(ThemeProvider, null, container);
}

More Configurations

WinJS allows plugins to register runtime configurations. If you use plugins, you will definitely find more runtime configuration options in the plugins.

Released under the MIT License.