1

前端临床手札——webpack构建逐步解构(上)

工作流程

clipboard.png

案例:multiple-page-vue-webpack-example

最近添加了雪碧图功能,并把sass-loader替换成postcsspress,详细可以看分支develop

构建生产

上一篇说完了本地测试webpackexpress是如何工作,接下来分析构建生产模式下webpack配置如何配置和每个模块干了什么。

从流程能看到,这里用到两个模块build.jswebpack。当你进入build.js文件能看到没干什么,其实这里可以理解为构建生产代码前的预处理部分(删除已构建的文件、拷贝静态资源相关的操作等),实际工作还是webpack完成的。

因此接下来说明的内容就剩下webpack配置了,打开webpack.prod.conf.js能看到前面设置也没什么大变化,但是添加的plugins却有点不同。

webpackConfig.plugins = [].concat(webpackConfig.plugins, utils.htmlLoaders(config.template, webpackConfig.entry), [
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),
    // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
    // new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash:5].css')),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      // TODO: set node_modules fallback
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    })
])

utils.htmlLoaders()上一篇说过了是多入口页面的设置,剩下的分别有:

  • webpack.optimize.UglifyJsPlugin()

  • webpack.optimize.OccurrenceOrderPlugin()

  • ExtractTextPlugin()

  • webpack.optimize.CommonsChunkPlugin()

接下来一个个讲解,首先是webpack.optimize.UglifyJsPlugin

webpack.optimize.UglifyJsPlugin

从名字能看出他是负责压缩处理js的,其他没啥好说的细节请看官方说明

webpack.optimize.OccurrenceOrderPlugin

这个看官方文档说明感觉是个处理分包的机制的插件,然而也没啥好说的了。

ExtractTextPlugin

这个插件用来合并css文件,除了最后压缩调用外,前面在所有输出css的配置也得使用上ExtractTextPlugin.extract()来提前提取css配置。由于封装到utils.jscssLoaders方法下,这里代码并没有体现出来。

webpack.optimize.CommonsChunkPlugin

这个得重点说一说,webpack厉害之处在于他分包的科学计算法的体现就是这个插件,能智能地帮你把代码拆分成多个包而已加载时并没依赖缺失,下面讲解配置,你也可以看官方文档

使用

new webpack.optimize.CommonsChunkPlugin(options)

配置说明

  • options.name 合并或拆分后的名字,多用于设置。

  • options.filename 这个当然是指生成出来的文件名字

  • options.chunks 指定js代码块来进行处理,默认使用的是入口文件及其依赖

  • options.children 这个具体有什么用博主还真没搞懂

  • options.async 设置为true,就可以创建一个异步请求的代码块

  • options.minSize 创建一个公共块之前的模块的最小尺寸,意思就是小于这个大小的块并不会合并

  • options.minChunks 最小分割成多少个代码块,设置为Infinity就不会进行合并代码。除此之外还可以设置方法,自己写合并规则,想案例就是这样处理的。

从案例分析,每个CommonsChunkPlugin将会是生成一个代码块,下面这段是生成一个入口公共块,同时必须在html-webpack-plugin的依赖添加上(参考文档utils.js

webpack.prod.conf.js

new webpack.optimize.CommonsChunkPlugin({
  name: 'manifest',
  chunks: ['vendor']
})

utils.js

Object.keys(pages).forEach(function(pathname) {
    let conf = {
      filename: path.normalize(pages[pathname][0].replace(template.replace(/\*\*.*$/,''),'')), //生成的html存放路径,相对于path
      template: pages[pathname][0], //html模板路径
      inject: false, //js插入的位置,true/'head'/'body'/false
    };
    if (pathname in webpackEntry) {
      conf.inject = 'body';
      conf.chunks = ['manifest','vendor', pathname];
      conf.hash = true;
      conf.chunksSortMode='dependency';
    }
    plugins.push(new HtmlWebpackPlugin(conf));
});

而下面这段,则是将node_modules目录下任何所需的模块提取到vendor.js

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  // TODO: set node_modules fallback
  minChunks: function (module, count) {
    // any required modules inside node_modules are extracted to vendor
    return (
      module.resource &&
      /\.js$/.test(module.resource) &&
      module.resource.indexOf(
        path.join(__dirname, '../node_modules')
      ) === 0
    )
  }
})

最后

到这里估计对webpack配置的比较迷惑的同学已经清晰了多少,然而这篇并不是从头帮你解析webpack所有配置的文章,内容和标题货不对板有点抱歉,却还是希望不懂的人自己多看官方文档,官方文档很多时候已经说得比较清楚。我自己也是经常使用一些插件时懵逼了去google找其他人使用的帮助,然而半天没找到比较靠谱的方法,最后还是反复啃官方文档或者看源码解决的。所以或许这篇文章不能真正解决你的疑惑,但愿能很好地教会你看官方文档;)。

然后在写完这篇文章后,发现webpack还是有些功能需要gulp补充的,比如css的压缩、图片的处理(雪碧图、svg等),希望最近能有空补上这块内容吧!


帕奇式
924 声望71 粉丝

设计和管理是毕生的课题👨‍💻