单页应用——代码分割

前提说明

在单页应用中的代码分割和多页应用中的代码分割有一定的区别:

  • 多页应用的代码分割可以通过 Webpack 的配置来实现
  • 单页应用的代码分割只能通过代码中的动态指定 webpackChunkName 来实现

准备工作

为了获取一致的代码体验,这里还是习惯性的把所依赖的模块贴出来:

  "devDependencies": {
    "webpack": "^4.17.1",
    "webpack-cli": "^3.1.0"
  },
  "dependencies": {
    "lodash": "^4.17.10"
  },
  "scripts": {
    "webpack": "webpack"
  }

由于单页应用的入口只有一个,且代码分割的内容不是在配置文件中,而是在实际的代码中,在这里可以直接把所需要的配置贴出来:

const { resolve, join } = require('path');

module.exports = {
  mode: 'production',
  entry: {
    index: resolve(__dirname, './src/index.js')
  },
  output: {
    path: resolve(__dirname, './dist'),
    filename: '[name].bundle.js',
    chunkFilename: '[name].chunk.js',              // 根据 chunk name 生成对应的文件
    publicPath: join(__dirname, './dist/')      // 入口 bundle 查找其他 chunk 依赖的路径
  }
};

程序的入口是 index.js,页面中存在两个组件 headerfooter,这两个组件又共同引入了组件 component.js,在代码中体现,如下:

index.js

import './header';
import './footer';

header/index.js

import '../component/component';

console.log('header section ...');

export default 'footer';

footer/index.js

import '../component/component';

console.log('footer section ...');

export default 'footer';

component/component.js

import _ from 'lodash';

console.log(_.join(["Hello", "lodash"]));

export default 'component';

创建一个 index.html 加入打包后的入口 js,为了便于观察效果:

<body>
  <script src="./dist/index.bundle.js"></script>
</body>

未进行代码分割的效果

准备工作完成之后,首先来看一下没有经过代码分割的效果。首先执行命令:yarn webpack

          Asset      Size  Chunks             Chunk Names
index.bundle.js  1.07 KiB       0  [emitted]  index
Entrypoint index = index.bundle.js

这个时候所有的代码都会打包到 index.bundle.js 中,也就是没有进行代码分割。

进行代码分割

下面的操作就是把所有的代码都分割成单独的 chunk,便于懒加载(懒加载下篇文章说明)。

如果要把所有的 module 都分割成单独的 chunk,就需要使用 import() 方法,并且在该方法的参数中指定 webpackChunkName 来告诉 Webpack 如何分离 chunk。

index.js

import(/* webpackChunkName: 'header' */ './header').then(module => {
  console.log(module);
}).catch(err => {
  console.log(err);
});
import(/* webpackChunkName: 'footer' */ './footer').then(module => {
  console.log(module);
}).catch(err => {
  console.log(err);
});

header/index.js

import(/* webpackChunkName: 'component' */ '../component/component').then(module => {
  console.log('in header : ', module);
}).catch(err => {
  console.log(err);
});

console.log('header section ...');

export default 'footer';

footer/index.js

import(/* webpackChunkName: 'component' */ '../component/component').then(module => {
  console.log('in footer : ', module);
}).catch(err => {
  console.log(err);
});

console.log('footer section ...');

export default 'footer';

component/component.js

import(/* webpackChunkName: 'lodash' */ "lodash").then(function(_) {
  console.log(_.join(["Hello", "lodash"]));
});

export default 'component';

执行命令后的效果:

                  Asset       Size  Chunks             Chunk Names
        index.bundle.js   2.24 KiB       0  [emitted]  index
        header.chunk.js  247 bytes       1  [emitted]  header
        footer.chunk.js  248 bytes       2  [emitted]  footer
     component.chunk.js  212 bytes       3  [emitted]  component
vendors~lodash.chunk.js   69.5 KiB       4  [emitted]  vendors~lodash
Entrypoint index = index.bundle.js
posted @ 2018-08-28 16:54  沫俱宏  阅读(466)  评论(0编辑  收藏  举报