webpack中的代码分割中的常见方法

代码分割是webpack的一个重要特性,可以将代码分割成不同的部分(bundle),以便进行后续的按需加载和并行下载,对提升项目性能起着重要的作用

方法一:webpack入口文件配制成多个文件

const path = require('path');
module.exports = {
	//entry也可以是数组,例如entry:['./src/index.js', './src/another-module.js']
	//为数组时不会生成多个bundle
	//此时entry是对象
  entry: {
    index: './src/index.js',
    another: './src/another-module.js'
  },
  output: {
   //[name]是entry的键值,[hash]是打包时候的hash值
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

看上去分割成多个bundle,但是会出现以下问题

  1. 如果入口bundle包含多个相同模块(例如index.js和another-module.js都引入了 lodash)则会打包两遍
  2. 这种方法不够灵活,完全依照配置打包,并且不能将核心应用程序逻辑进行动态拆分代码

⚠️:解决1的问题可以使用CommonsChunkPlugin(已在 webpack v4
中移除,类似插件可以采用SplitChunksPlugin,官网地址)插件来解决重复打包相同文件问题

const path = require('path');
module.exports = {
  entry: {
    index: './src/index.js',
    another: './src/another-module.js'
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common' // bundle 名称
    })
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

此时可以看到打包文件中多出common bundle,这个bundle就是抽离出来的公共模块

方法二:动态导入

Webpack 的动态分割主要方式是使用符合 ECMAScript 提案的 import() 语法。例如import(’./a.js’).then(_module => {})。
import()会返回一个Promise对象,意味着这个模块和它的子模块都会被分割成一个单独的 bundle。
在Vue项目中,动态分割是实现按需加载的前提,按需加载需要实现以下要求:

  1. 将每个路由对应的组件都打包成一个单独的bundle(根据import()已经实现)
  2. 当路由被访问的时候才加载该路由对应的 bundle(用到 vue 里面的异步组件特性)

Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。

Vue.component('async-example', function (resolve, reject) {
  setTimeout(function () {
    // 向 `resolve` 回调传递组件定义
    //resolve返回一个fullfilled的Promise,而 import() 也是返回 Promise 
    resolve({
      template: '<div>I am async!</div>'
    })
  }, 1000)
})

使用 import() 后,工厂函数的写法:

Vue.component('async-webpack-example',
  // 该 `import` 函数返回一个 `Promise` 对象。
  () => import('./my-async-component')
)

最后在 vue-router 的路由配置中,我们只需要这么写:

const router = new VueRouter({
  routes: [
    { path: '/login', component: () => import('@/views/login'), },
    { path: '/home', component: () => import('@/views/home'), }
  ]
})

方法三:预获取/预加载模块

Webpack官方是希望我们使用异步的方式来进行模块的加载的。而且异步加载也能提升首页加载速度,但是又会导致异步加载的那部分代码逻辑迟迟不能执行,可能导致用户的交互长时间没有响应。

这个时候就需要prefetch或preload了。
在声明 import 时,使用下面这些内置指令,可以让 webpack 输出"resource hint(资源提示)",来告知浏览器:

  • prefetch(预获取):将来某些导航下可能需要的资源(指示浏览器在空闲时间加载)
  • preload(预加载):当前导航下可能需要资源(会在父 bundle 加载时,以并行方式开始加载)
import(/* webpackPrefetch: true */ './path/to/LoginModal.js');
//实际上这样做,Webpack替我们在head内添加了这样一行:
<link rel="prefetch" as="script" href="0.js">

参考链接

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值