The reason for this is this. Recently, a considerable part of the energy has been devoted to the performance optimization of the project. There was a long-standing problem in a project that has been tangled for a long time, and I haven't had time to look at it. This problem is very simple: the project I created with vue-cli, according to the vue routing lazy loading writing method, but found that the code is not divided after packaging, all are packaged into app.js, resulting in app.js is too large, and Loading on demand without routing.

Find out the cause of the problem

I started to think that the problem may be caused by the following points:

  1. Route lazy loading is wrong;
  2. vue-cli version problem;
  3. The configuration problem of vue-cli.

But these three possible reasons were quickly ruled out, because there was a project where the above three were the same, and the code division was normal, so it could only be a code problem. But there are so many files that you can't review all of them. If you have no clue, you can only use a simple but practical dichotomy to locate the problem files. After some physical work, I finally found two culprits. By observing these two files, I found that the same file reference method was used. The similar code is as follows:

 let form = null;
let cpnName = this.template.name;
this.$options.components[cpnName] = require('@/' + this.template.path).default;
form = <cpnName />
return (
    <div>{form}</div>
)

Components dynamically import components by splicing the path of the input parameters. In fact, I probably know the reason when I see it here. Because it is a dynamic path, webpack is a static analysis dependency when packaging, and the specific address of the file cannot be confirmed at all, so all the code is caused. All hit app.js. To prove my idea, I went to webpack's github issue and found a scenario similar to mine:

This old man wants to dynamically import pictures according to the incoming picture name, but when packaging, it is found that pictures in other directories are also packaged in. The maintainer of webpack also replied that this is the working mechanism of require, it does not know Whichever resource you use, it packs them all.

verification problem

To verify this problem, I created a project to reproduce the problem:

The dynamically imported component code is as follows:

 // src/components/common/DynamicRequireCpn.vue
<script>
export default {
    name: 'DynamicRequireCpn',
    props: {
        template: Object
    },
    render () {
        let form = null;
        let cpnName = this.template.name;
        this.$options.components[cpnName] = require('@/' + this.template.path).default;
        form = <cpnName />
        return (
            <div>{form}</div>
        )
    }
}
</script>

The routing code is as follows:

 // src/router/index.js
const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
];

The packaging result is as follows:

It is found that the code is still packaged together, and the about component is not divided. And I also found unreferenced code in app.js. That is to say, in this case, webpack packs all the files in the src directory.

solution to the problem

According to the above experiment and the working principle of require, I think whether the problem can be solved by narrowing the search scope of require?

 <script>
export default {
    name: 'DynamicRequireCpn',
    props: {
        template: Object
    },
    render () {
        let form = null;
        let cpnName = this.template.name;
        this.$options.components[cpnName] = require('@/components/common/' + this.template.path).default;
        form = <cpnName />
        return (
            <div>{form}</div>
        )
    }
}
</script>

Now I've made the dynamic path of require accurate to @/components/common/ and repackage it to see:

Bingo! I saw the split file corresponding to the about component, and searched for the app.js file, but no unreferenced code was found. The problem is solved!

Summarize

When using webpack, you should minimize the import of dynamic paths of resources. If you must import in this way, you should also try to pass in a shorter file path, or put the files to be dynamically imported under a directory to prevent webpack from finding non-target directories. under.

GOOD

require('@/components/common/' + this.template.path);

BAD

require('@' + this.template.path);


不死小强
2.2k 声望587 粉丝

前端开发