(Note: VuE-CLI 2.x is used as an example.)

Demand generation

At the beginning, our project was just a simple scaffold building project, until one day, the company decided to issue another version on the existing basis, the existing content remains unchanged, two versions coexist, there may be more versions in the later stage, as a front-end, how do we do the best?

Big 0: Open a new branch and do it, Big 1: But now the project has done a lot of packaging configuration, and there are a lot of reusable components and packaged classes, what if one day these things need to change, I can’t change all branches, Big 2: We can upload it to our company’s Git and re-pull it when the public content changes. The little Prince: Can we split our projects vertically like distributed? Extract the common parts, and then compile them in modules, everyone:…

Emmmmm, that’s weird. How do you do that?

Webpack runs the process

First take a look at the default file structure

main.js
index.html

File structure changes

Since we are going to use multiple entry packages, we can no longer use a set of entry files (main.js) and template files (index.html), we create them separately under different modules. When we package module A, it automatically accesses module A’s main.js and index.html. By packaging module B, it automatically accesses module B’s main.js and index.html. So our file structure is going to look something like this,

The data warehouse
store

implementation

1. Yargs: receives command line parameters

Nodebuild /build.js --env module1 receives the parameter const yargs = require('yargs') const module_fileName = yargs.argv.envCopy the code

We can extract the method that receives the parameter to the public part, because the packaging file corresponding to the production environment and development environment needs to use it, we can directly call the method value where it is used.

Add the following code to build/utils.js file + const yargs = require('yargs') + const fileName = yargs.argv.env + // custom entry main.js + exports.entry = function () { + return { + app: './ SRC /modules/' + fileName + '/main.js' +} +} + // custom entry HTML file + exports.template = function () {+ return './src/modules/' + fileName + '/index.html' + }Copy the code

2. Dynamically read main.js and index.html

2.1. The main js

As an entry file, the production environment and development environment are entered from here, which is part of the base configuration, so we find webpack.base.conf.js

In the build/webpack base. Conf. Js file to modify entry entry: utils. Entry (),Copy the code

2.2. The index. HTML

Template files are a bit more complicated to use, as they are needed in both production and development environments, as well as for our hot updates

  • Start by modifying the development environment

    In the build/webpack. Dev. Conf. Js modified devServer. HistoryApiFallback. Rewrites devServer: {historyApiFallback: {rewrites: [{the from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, utils.template())}, ], } ... } in the build/webpack. Dev. Conf. Js modified plugins plugins: [new HtmlWebpackPlugin ({filename: utils. Template (), the template: utils.template(), inject: true }), ... ]Copy the code
  • Then modify the production environment

    In the build/webpack. Dev. Conf. Js modified plugins plugins: [new HtmlWebpackPlugin ({template: utils. Template (),...})]Copy the code
  • As a final test, we execute two commands separately

    NPM run dev:module1 NPM run dev:module2 After the compilation passes, webPack starts two servers, one for module1 and the other for Module2, which indicates that our change is effectiveCopy the code

3. Modular data warehouse

3.1 The scheme provided by the official website

Vuex itself provides a solution for modularity of data warehouses

Vuex allows us to split the Store into modules. Each module has its own state, mutation, action, getter, even nesting child module, from top to bottom in the same way of dividing vuex.vuejs.org/zh/guide/mo…

Modules are officially recommended, and registerModule can be used to introduce data warehouse on demand, which is a good optimization solution.

But our project was not built with this situation in mind. Adopting this scheme means that we need to modify every component that uses VUEX, which requires a lot of engineering. If you are in the same situation as us, you may consider the following scheme.

3.2 File merge scheme (require + object.assign)

The structure of the file that we showed at the beginning of this article, the data warehouse in the project root directory, module1 and Module2 just need to import the data warehouse modules as needed and we’ll do that here,

First take a look at the data warehouse under the root directory

We introduced it on demand in Module1

src/module1/store/config.js
  export [
    'common',
    'alarm',
    'params_3dCity',
    'params_sky',
    'queue_message',
    'user_city'
  ]
Copy the code

With this, we can dynamically import the file require, then use object. assign to merge the objects, and finally export an instantiated vuex. Store Object, which can be used directly by main.js.

The following code

src/module1/store/config.js
  
  import Vue from 'vue'
  import Vuex from 'vuex'
  Vue.use(Vuex)
  import config from './config'
  
  const state = {};
  const mutations = {};
  const actions = {};
  
  for(let fileName of config) {
    const module = require('@/store/' + fileName);
  
    Object.assign(state, state, module.default.state);
    Object.assign(actions, actions, module.default.actions);
    Object.assign(mutations, mutations, module.default.mutations);
  }
  
  export default new Vuex.Store({
    state,
    mutations,
    actions,
  })
Copy the code

4. Configure commands and compile them as required

Add the following command + "dev:module1" to package.json: "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --env module1", + "dev:module2": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --env module2", + "build:module1": "node build/build.js --env module1", + "build:module2": "node build/build.js --env module2",Copy the code

conclusion

  • Multi-entry packaging has requirements for both production and development environments, so the content of entry changes according to parameters
  • Extract as much of the public as possible, including assembled public classes, util functions, public components, and so on
  • Reduce the coupling of the common part with each module, and try not to write business in the common part. If necessary, just extends the common component in the module, and then write something unique in the module
  • According to the requirements of the data warehouse, the official recommended solution can be used in conjunction with registerModule for on-demand loading. The solution in this article only demonstrates one solution, and the official solution is recommended if the workload is not too heavy.