在 Webpack 中执行代码分割

有三种常用的代码分离方法:

  • 入口起点:使用 entry 配置手动地分离代码。
  • 防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。
  • 动态导入:通过模块的内联函数调用来分离代码。

1、入口起点

这是迄今为止最简单、最直观的分离代码的方式。不过,这种方式手动配置较多

webpack.config.js

const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    index: './src/index.js',
    another: './src/another-module.js'
  },
  plugins: [
    new HTMLWebpackPlugin({
      title: 'Code Splitting'
    })
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};
这将生成如下构建结果
Hash: 309402710a14167f42a8
Version: webpack 2.6.1
Time: 570ms
            Asset    Size  Chunks                    Chunk Names
  index.bundle.js  544 kB       0  [emitted]  [big]  index
another.bundle.js  544 kB       1  [emitted]  [big]  another
   [0] ./~/lodash/lodash.js 540 kB {0} {1} [built]
   [1] (webpack)/buildin/global.js 509 bytes {0} {1} [built]
   [2] (webpack)/buildin/module.js 517 bytes {0} {1} [built]
   [3] ./src/another-module.js 87 bytes {1} [built]
   [4] ./src/index.js 216 bytes {0} [built]
 

正如前面提到的,这种方法存在一些问题:

  • 如果入口 chunks 之间包含重复的模块,那些重复模块都会被引入到各个 bundle 中。
  • 这种方法不够灵活,并且不能将核心应用程序逻辑进行动态拆分代码。

2、防止重复

CommonsChunkPlugin 插件可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk。让我们使用这个插件,将之前的示例中重复的 lodash 模块去除:

webpack.config.js

  const path = require('path');
+ const webpack = require('webpack');
  const HTMLWebpackPlugin = require('html-webpack-plugin');

  module.exports = {
    entry: {
      index: './src/index.js',
      another: './src/another-module.js'
    },
    plugins: [
      new HTMLWebpackPlugin({
        title: 'Code Splitting'
- })
+ }),
+ new webpack.optimize.CommonsChunkPlugin({
+ name: 'common' // 指定公共 bundle 的名称。
+ })
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };

这里我们使用 CommonsChunkPlugin 之后,现在应该可以看出,index.bundle.js 中已经移除了重复的依赖模块。需要注意的是,CommonsChunkPlugin 插件将 lodash 分离到单独的 chunk,并且将其从 main bundle 中移除,减轻了大小。执行 npm run build 查看效果:

Hash: 70a59f8d46ff12575481
Version: webpack 2.6.1
Time: 510ms
            Asset       Size  Chunks                    Chunk Names
  index.bundle.js  665 bytes       0  [emitted]         index
another.bundle.js  537 bytes       1  [emitted]         another
 common.bundle.js     547 kB       2  [emitted]  [big]  common
   [0] ./~/lodash/lodash.js 540 kB {2} [built]
   [1] (webpack)/buildin/global.js 509 bytes {2} [built]
   [2] (webpack)/buildin/module.js 517 bytes {2} [built]
   [3] ./src/another-module.js 87 bytes {1} [built]
   [4] ./src/index.js 216 bytes {0} [built]

以下是由社区提供的,一些对于代码分离很有帮助的插件和 loaders:

CommonsChunkPlugin 插件还可以通过使用显式的 vendor chunks 功能,从应用程序代码中分离 vendor 模块。

3、动态导入

当涉及到动态代码拆分时, 一般使用使用webpack提供的符合 ECMAScript 提案 的 import() 语法

new Vue({ 

  el: '#app',
  components: {
    AsyncComponent: () => import('./AsyncComponent.vue')
  }
});

实施代码分割并不难,难在搞清楚在什么时候、什么地方进行。

Vue.js 单页应用进行代码分割有三种思路:

  • 按页面分割
  • 使用折叠
  • 按条件分割

1. 按页面

按页面来进行代码分割,是最明显的一种方式。

如果能确保每个单文件组件代表一个页面,如 Home.vueAbout.vue 以及 Contact.vue,那么我们就可以使用 Webpack 的 "动态导入" 函数 (import) 来将它们分割至单独的构建文件中。之后后,当用户访问一个新页面的时候,Webpack 将异步加载该请求的页面文件。

如果用到了 vue-router,由于页面已经分割成了单独的组件,实施起来会非常方便。

 const Home = () => import(/* webpackChunkName: "home" */ './Home.vue'); 
 const About = () => import(/* webpackChunkName: "about" */ './About.vue'); 
 const Contact = () => import(/* webpackChunkName: "contact" */ './Contact.vue'); 
 const routes = [ 
 { path: '/', name: 'home', component: Home }, 
 { path: '/about', name: 'about', component: About }, 
 { path: '/contact', name: 'contact', component: Contact } 
 ]; 

代码编译完成后,通过查看生成的统计数据得知:每个页面都有自己单独的文件,同时有多出来一个名为 build_main.js 的打包文件。里面包含一些公共的代码以及逻辑,用来异步加载其它文件,因此它需要在用户访问路由之前加载完成。

2. 折叠

“折叠” 是指页面初次加载时,视图的不可见部分。用户通常会花费 1~2 秒来浏览可视区域,特别是第一次访问网站的时候(可能更久),之后才开始向下滑动页面。
这个时候,可以异步加载剩余的内容。

3. 条件展示内容

代码分割另一种比较好的备选方式,是按条件展示。比如:模态框、标签页、下拉菜单之类。

如果我们需要一个模态框,给模态框设置 v-if 属性,绑定了 show 变量。一方面用来控制模态框是否显示,同时也决定了是否应该渲染模态框组件。当页面加载的时候,它的值为 false,模态框的代码只有当它显示的时候才会被加载。如果用户永远不打开这个模态框,这部分代码就永远不会被下载。缺点是,可能会增加很小的用户体验成本:用户点击按钮后,需要等待代码文件下载完成。

猜你喜欢

转载自blog.csdn.net/u012207345/article/details/81356299