Background:

This project has several years of sedimentation, using WebPack3.6.0 + vue2.5.2 + ivew2.x, change configuration tired, unfamiliar, and Webpack4 added a lot of features and optimization, there are more concise configuration, can also be customized segmentation code blocks, etc. Improved project construction speed and compilation speed, reduced package volume and so on, the original configuration file directly do not need to be configured in vue.config.js. At first glance, it seems that upgrading would be more cost-effective, and I haven’t tried it, so wanting to try it is a big part of the reason.

Why:

  • The WebPack configuration file is cumbersome (mostly not very familiar), and the higher version has more room for optimization and content.
  • Some es6 features and later new features, such as optional chain operations, are unavailable
  • The component library was old, a lot of functionality was unimplemented, I had to write my own logic (by no means lazy), and MIXED elementUI
  • If I want to deploy something else later, I may have to work overtime if I force webpack.

What did I do this time

  • webpack 3.x –> vue cli 4.x(webpack4)
  • Vue 2.5 –> Vue 2.6
  • iview 2.x –> iview 4.x
  • Related dependency upgrade and compatibility processing

Upgrade Process (Webpack -> Vue CLI)

Create a new VUE project

vue create xxx
Copy the code

Then migrate the directory files to the/SRC directory. I’m going to introduce that into the global substitution, just be careful not to make the substitution wrong.

Take a look at the directory structure before and after:

/public places the old HTML and the external rich text component (that is, /static); / SRC /assets to put the old /common + /assets(old /common to put fonts and CSS,/assets to put images); /store is the predecessor of /vuex. It is not a good name to use vuex as the folder name.Copy the code

01 rely on

After moving the project, you need to install all the used dependencies. You need to see if any of the old dependencies are still useful and don’t move them all over.

I had installed the main dependency packages, commented out references in main.js such as component libraries that didn’t affect the project, and then just ran and got all red-hot. Once you’re done with this, open the references in main.js one by one, and then handle them accordingly.

Here is mainly to install dependencies, upgrade the reduced dependency version, so that they can be compatible with each other, do not fight, according to the error prompt processing

I installed it according to the error reported in it, and then I encountered several profound problems as follows (many of them may feel that they are small problems and have not been recorded):

  1. The original Babel dependency looked something like this. And in VCLI4 it looks like @babel/… (Not all of them, of course, depending on which one you use, you can check them separately).

  2. Note whether the versions of the dependencies match, and if some versions are incompatible, an error will be reported. Try to keep the family as tidy as possible.

  3. Error this.getoptions… What what;

    • I’m here becauseless-loader8The above version uses webpack5, I reduced it to7.3.0Can.
  4. Autoprefixer applies control comment to whole block, not to next rules.

    • This is aAutoprefixerNote out the problem, refer to this articleAutoprefixer reported an error solution;
    • It’s the second one in a nutshellAutoprefixerComments are ignored,AutoprefixerComments should be used for the entire code block, not the next rule. That is/* autoprefixer: off */Can no longer operate on phi in a code block/* autoprefixer: on */;
    • I deleted all of the second global comments (I think it might be a version problem, but I didn’t try to find the correct version, so I’m just going to leave it that way).
  5. Error evaluating function rgba: color functions take numbers as parameters

    • CSS RGBA only set three color values, change to RGB, the reason is unknown, guess is caused by a CSS plug-in;
    • There is also CSS separation packaging, reference order conflict, reverse order, or ignore configuration.
  6. TypeError: Cannot read property 'vue' of undefined

    An error occurs during the configuration of vue-loader. Upgrade vue-loader to the latest package.

    Problem: after upgrade, findIndex can not be found, find a solution for a long time, so it is not set in configuration file 💡 guess: - Other dependency versions conflict - it may be that vue-CLI has been built in, which is caused by repeated introduction here - it may also be that I wrote the wrong configuration file (read several times, feel correct, do not want to believe it)Copy the code

Update component library and various style issues

Iview2 is not compatible with later versions of VUE, so this has to be done. Upgrade component library mainly refer to the official upgrade 4.x guide;

  • Package swap, switch import, install iView-Loader dependencies, and other extra things to do:

    • The class name of the icon tag has been changed and needs to be changed.
    • And the I tag in the project was usediviewClass name, need to change one by one

    Attached ivew-loader configuration in vue.config.js:

    chainWebpack: config= >{
        config.module
          .rule('vue')
          .test(/\.vue$/)
          .use('iview-loader')
          .loader('iview-loader')
          .tap(args= > {
            return {
              prefix: false
            }
          }).end()
    }
    Copy the code
  • The next step is to introduce global less files

    1. Implementation-content: start; To flex – start;

    2. Calc calculation error in less file:

      Similar to calc(100Vw-66px); Calc (~” 100vw-66px “); calc(~” 100vw-66px “);

    3. The base style of the production environment does not take effect after packaging

      There is a configuration in package.json where sideEffects takes care of things that are considered sideEffects, such as CSS; I don’t know if it’s silly or I’m silly, so I configure CSS, Vue, less, and tell it, these types of files I cover!

      Then I realized that the iView style didn’t work in the production environment, so I was tired, I threw in the towel, and I just used CDN to introduce the iView in the production environment. Then the scum must throw the iView and then the ViewUI as the others do:

      {
        vue: 'Vue'.vuex: 'Vuex'.'vue-router': 'VueRouter'.axios: 'axios'."view-design": 'iview'.// iView4 throws iView first, then ViewUI
        "iview": "ViewUI"
      }
      Copy the code
    4. Finally, there was the problem of common styles not working or overwriting each other. After staring at the code for a long time, I changed the order introduced in main, and it finally seemed to run normally.

  • There is also an ivew form after the upgrade of the verification is more strict than the old version, the original non-standard writing method has to find out one by one to write the specification point:

    • For example, there is a prop in the FromItem component, and the content in the prop is not in the form. It may be forgotten to delete it when copying, or for other reasons, so the form will fail verification and need to be deleted or changed to the correct one.
    • Etc. (mostly I don’t remember, some of them are on record, some of them are completely forgotten)

03 Packaging Optimization

🚨 to optimize the time to give me a collapse, almost collapse mentality, back to a lot of code, want to cry

  • Vue. Config.js: externals import external resources from webpack: externals import external resources from webpack

    const cdnMap = {
      js: [
        CDN_URL + '[email protected]',
        CDN_URL + '[email protected]',
        CDN_URL + '[email protected]',
        CDN_URL + '[email protected]',
        CDN_URL + '[email protected]']},const externals = {
      vue: 'Vue'.vuex: 'Vuex'.'vue-router': 'VueRouter'.axios: 'axios'."view-design": 'iview'.// iView4 throws iView first, then ViewUI
      "iview": "ViewUI"
    }
    module.exports = {
        chainWebpack: config= >{
            if(IS_PRO){
                config.externals(externals);
                config.plugin('html').tap(args= > {
                    args[0].cdn = cdnMap
                    returnargs }); }}}Copy the code
    index.html
        <% if(process.env.NODE_ENV==='production' ){ %>
          <! -- CDN loaded js -->
          <% htmlWebpackPlugin.options.cdn.js.forEach( function(item) { 
            if(item) { %>
              <script type="text/javascript" src="<%= item %>"></script><%}) %> <%} %>Copy the code
  • Add package analysis

    npm install webpack-bundle-analyzer --save-dev
    Copy the code
     module.exports = {
        chainWebpack: config= >{
            config.plugin('webpack-bundle-analyzer')
                .use(bundleAnalyzer.BundleAnalyzerPlugin, process.env.npm_config_report)
        }
    }
    Copy the code
  • Compressed JavaScript

    npm install uglifyjs-webpack-plugin --save-dev
    Copy the code
    const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin'); .module.exports = {
        configureWebpack: config= > {
            config.plugins.push(
                new UglifyjsWebpackPlugin({
                  uglifyOptions: {
                    compress: {
                      drop_debugger: true.drop_console: true.// The production environment automatically deletes the console
                      pure_funcs: ["console.log"] / / remove the console
                    },
                    warnings: false,},sourceMap: false.parallel: true.// Use multiple processes running in parallel to speed up builds}}}))Copy the code
  • Split chunk as needed to reduce repeated dependency of modules and merge common modules

    The CommonsChunkPlugin was used to avoid overlapping dependencies between chunks, but starting with WebPack V4, the CommonsChunkPlugin was removed. Instead, optimization.splitchunks (this is a quote from the official website, but it is detailed);

    module.exports = {
        configureWebpack: config= > {
            config.plugins.push(
                new webpack.optimize.SplitChunksPlugin({
                  chunks: "async".minSize: 20000.// The minimum volume allowed for new chunks to be split, which is also the mandatory split volume of asynchronous chunks
                  maxAsyncRequests: 30.// Maximum number of parallel requests when loading on demand
                  maxInitialRequests: 30.// The maximum number of parallel requests at the entry point
                  automaticNameDelimiter: '~'.cacheGroups: { / / cache group
                    vendors: {
                      name: `chunk-vendors`.test: /[\\/]node_modules[\\/]/,
                      priority: 10.// Cache group weight, the higher the number, the higher the priority
                      chunks: 'initial' // Only initial chunks are processed
                    },
                    common: {
                      name: `chunk-common`.minChunks: 3.// Modules in the common group must be shared by at least 3 chunks
                      priority: 0.chunks: 'initial'.// Only for synchronous chunks
                      reuseExistingChunk: true // Reuse dependencies that have been removed instead of being included in the group together}},}))}}Copy the code
  • Enable GZIP compression

    npm install compression-webpack-plugin --save-dev
    Copy the code
    const CompressionWebpackPlugin = require("compression-webpack-plugin");
    const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\? . *)? $/i; .module.exports = {
        configureWebpack: config= > {
            config.plugins.push(
                new CompressionWebpackPlugin({
                  asset: '[path].gz[query]'.algorithm: 'gzip'.test: productionGzipExtensions,
                  threshold: 10240.// Compress over 10K
                  minRatio: 0.8 // Compression ratio}}}))Copy the code

conclusion

A project with several years of history, various writing methods, various styles, in the pursuit of the principle of running, or quite tangled whether to do it, but looking at the later version will also be a big knife, then go with the trend;

Generally speaking, the final outcome is still satisfactory, and the later period is basically some trivial details are modified, most of which is due to the upgrade of the component library. It can also be seen that the various usage and writing methods of the original component library are not rigorous enough, and some historical bugs are also changed. Still left a trifling problem did not consider thoroughly, the back again pondered pondered see.

Before this little finishing once structure project, the subsequent break direction should be mainly to routing and the content of the utility module this piece, now routing deeply nested hierarchy, also has a lot of redundant code, temporary idea is first out of those old yao have to use the code, then the common method this piece to do, After the whole project is clear, we will do the routing and finally make an overall optimization. So there should be two more moves. That’s it for now, for the record.

I am still a small rookie, the above if there is a mistake in the words of the hope not stingy give advice, very thank you!