前端 Webpack 工程化的最佳实践( 二 )

  • 线上的产品的一些个性诉求(比如,对同一份Javascript代码也许要匹配不同的样式文件)等 。
  • 3. 通常评估效率维度主要有以下几个,稳重提到的数据来源主要属于前三个:
    • 本地开发compile(w/ DLL or NO DLL)
    • 本地开发re-compile(w/ DLL or NO DLL)
    • 本地测试build(webpack analyse分析的重点部分)
    • 云构建时长 (NO DLL or 配置化OSS支撑DLL)
    在Webpack的新版本中,webpack-merge: 4.2.1 这个独立包的使用,开发者使用webpack.common.js文件对开发和生产环境中的公共部分进行配置,webpack.dev.js针对开发环境,webpack.prod.js针对生产环境 。区分后,两种环境的配置差异,一目了然:
    前端 Webpack 工程化的最佳实践

    文章插图
    (图:webpack配置文件结构)
    关于cz.config.js和flowGlobalVars.js里面“话题点”颇多,不在此处重点描述 。
    如果需要DLL配置(在后面的优化部分会重点讲),还需要单独加入一个webpack.dll.js打包的配置文件 。当然,dll其实也是一个普通的文件Output,我们可以在webpack.common.js文件中module.exports时,写两个区分开 。通过这种不是很常见的灵活写法(Exporting multiple configurations),可以更多的去理解文件的I/O和module模块的概念 。
     基础/自定义配置
    ? CommonsChunkPlugin被取代
    被移入到了webpack.optimization.splitChunks中 。有关拆包切分和颗粒度控制,这个其实从Webpack的层面已经为我们做了很多优化,自身也是有一套基础默认的优化策略的 。类比来看,React生态里面diff算法本身也是有策略机制的,更多的优化,使用者可以在这个对象里面加入回调方法,自己去细化控制 。
    这里需要特别注意的是cacheGroups,当不明确哪些内容需要被cache时,或者是颗粒度不好把控时,这样的切分会给我们带来非常多的冗余文件 。下面的代码中,定义了一个vendors对象,那么我们的output文件(不包含chunksFiles)的每一个都会生成一个cache文件 。加入output的有app.bundle.js和polyfill.bundle.js,一旦加入这个vendors对象,打包的时候会额外的生成两份文件,分别是vendors-app.js和vendors-polyfill.js 。虽然不用担心这两个文件内容会重新打包代码进去,里面只是放一些cache索引,但这两个文件如果在不确定要用他们来做什么的时候,cacheGroups的设置,需要重新认真去考虑 。
    ? OccurrenceOrderPlugin
    本身不在是一个webpack类下面的构造器,而是被重新命名(之前的名称因为单词拼写错误了),然后放入到新的位置,调用起来需要重新去书写:new webpack.optimize.OccurrenceOrderPlugin 。
    ? terser(默认的内置压缩工具包)
    webpack.optimization.minimizer的新版本中,default built-in的工具已经由旧有的uglifyJS变成了terserJS,旧的uglify已经被depreacted处理,相信不久之后的状态就会变成legacy,新的terser更好的性能,对ES6+的语法支持的更多,也同时兼容了babel 7的生态,同步其它第三方库代码压缩后的诉求 。目前我在使用的是terser-webpack-plugin,和普通的terser配置的参数上有一些差异,需要自己手动引入(官方文档推荐) 。
    ? module.rules.exclude[0]
    module.rules.exclude[0]的文件地址书写,要求更加严格(4.11.0以后的版本) 。
    以往我们在对module.rules做配置时,有些文件不希望被遍历到,那么我们通过exclude这个参数配置,将其跳过,有时候会使用'src/contianer/xx.jsx'这样的写法,如果是多个path索引,那就放到一个Array中就好 。但这种写法,在新版本中是不被允许的,我们只能使用path.resolve或/regExp/的写法去声明文件路径地址 。(Bonus Basic Tips,如何用正则书写并集和特定路径,如我希望include所有src加上一个指定的npm包: /(src/.*)|(node_modules/.*@ali/lark-components)/)
    ? alias和绝对路径
    webpack在打包的时候,通常需要对文件的路径去做查找、搜索,它需要明确知道文件的引用位置和引用关系,从而能够完整的知道整个映射mapping关系 。减少这方面的开销,我们可以考虑去配置alias,从而以绝对路径的写法代替大量相对路径写法 。好处的话,一方面是帮助webpack更快的去定位文件位置,另一方面书写起来,也不再用被输入 '../../*' 还是 '../../../*' 而困扰 。