2017-03-28 01:18:09

webpack自定义分块名称

之前我写了一篇如何优化SSR分块加载的文章,其中如何获得组件对应的分块是一大难点,博主当时也没有给出切实可行的办法

因此,本文介绍如何依靠分块的命名来简单达到目的。命名分块其实比较简单,一个api就够了,但是借此机会可以探究一下webpack的es6 module更新历程,因此有了本文

why

  • SSR 服务端进行分块加载优化
  • sw-toolbox的运行时缓存来缓存指定分块

总之,一旦指定了如分块名称,那么组件对应的分块在编译时就可以确定,之后无论做什么都方便多了

System.import

System.import()返回promise,它只有一个参数即文件路径。另外,System.import是es6 module形式的加载器,因此需要对应文件使用export关键字。

以前webpack2在rc版中允许import和module.exports的混用,正式版之后已经不行了 System.import已经在webpack2中被deprecated,并将在3.0中被移除

import

import作为es6 module的关键字,当它作为函数使用时会让人感到非常非常奇怪。但也不是不可以理解,毕竟原生es6 module语法并没有给出promise形式的模块导入。

作为System.import的替代,要说有什么更改,博主真的没注意到。因此,import同样无法指定分块id

System.import与import都支持部分动态的导入,例如import('../components/' + name),这样webpack会将components下所有符合的文件全部分块掉。但是,完全动态的名称就不会被支持了,因为webpack只是静态分析,不会去跑业务代码,因此import(name)这种纯变量形式就只能GG了。

require.ensure

require.ensure是weback1中的分块加载pai,它有三个参数,第一个参数为组件路径的数组,第二个参数为函数,在此函数中可以导入前一个参数中国的模块,第三个参数就是分块的名称了

具体形式如下:

new Promise((resolve)=> {
 require.ensure(['../components/Tag'], (modules) => {
  const result = require('../components/Tag')
  resolve(result)
  }, 'Tag') 
})

比较奇怪的是,第二个参数中modules是存在的但是并没有webpack1当中的加载效果了,而是需要直接require,另外比较残念的是,这个api并没有给reject的机会,并且写法仍然是CommonJS类型的,实在是不好看。

结尾

es6 module异步加载对后端来说感觉并没有什么用,博主个人觉得分块加载只是前端专用的一个功能。因此,为了兼容es6 module标准,System.import和import并没有多余的参数。

但是,webpack2更多是静态分析工具,因此System.import(path)这种变量形式是不被允许的,因为webpack2并不会帮你跑一遍代码,类似console.log的语句当然都是无效的。

怎样既能兼容es6 module标准,又能够获得分块加载的遍历呢?阅读本文的读者很大概率使用过istanbul和eslint,他们很多指令都是在注释中写的。webpack2作为与eslint相同种类(静态分析方面)的工具,因此注释也是一个可行的策略,尽管对webpack1的用户来说有一些奇怪。因此,针对import的分块命名的PR正好在本文写完前几个小时被提上了webpack2的官方仓库。

注意,在使用上面这种注释时,不要忘记将.babelrc中的comment设置为true,否则注释都没了自然webpack没法处理,之后多出来的注释再使用uglifyJSPlugin解决掉即可

本文链接:https://smallpath.me/post/webpack-on-demand-chunk-name

-- EOF --