目录(?)[-]
一文件结构
二指令分析
三build文件夹分析
builddev-serverjs
buildwebpackbaseconfjs
buildwebpackdevconfjs
buildutilsjs
buildvue-loaderconfjs
builddev-clientjs
buildbuildjs
buildwebpackprodconfjs
buildcheck-versionsjs
四config文件夹分析
configindexjs
configdevenvjsconfigprodenvjs和configtestenvjs
五总结
2017-09-11更新:更新到webpack 2.6.1所对应的配置,完善部分代码注释。
由于最近在vue-cli生成的webpack模板项目的基础上写一个小东西,开发过程中需要改动到build和config里面一些相关的配置,所以刚好趁此机会将所有配置文件看一遍,理一理思路,也便于以后修改配置的时候不会“太折腾”。
一、文件结构
本文主要分析开发(dev)和构建(build)两个过程涉及到的文件,故下面文件结构仅列出相应的内容。
二、指令分析
首先看package.json里面的scripts字段,
测试的东西先不看,直接看”dev”和”build”。运行”npm run dev”的时候执行的是build/dev-server.js文件,运行”npm run build”的时候执行的是build/build.js文件,我们可以从这两个文件开始进行代码阅读分析。
三、build文件夹分析
build/dev-server.js
首先来看执行”npm run dev”时候最先执行的build/dev-server.js文件。该文件主要完成下面几件事情:
检查node和npm的版本、引入相关插件和配置
webpack对源码进行编译打包并返回compiler对象
创建express服务器
配置开发中间件(webpack-dev-middleware)和热重载中间件(webpack-hot-middleware)
挂载代理服务和中间件
配置静态资源
启动服务器监听特定端口(8080)
自动打开浏览器并打开特定网址(localhost:8080)
说明: express服务器提供静态文件服务,不过它还使用了http-proxy-middleware,一个http请求代理的中间件。前端开发过程中需要使用到后台的API的话,可以通过配置proxyTable来将相应的后台请求代理到专用的API服务器。
详情请看代码注释:
build/webpack.base.conf.js
从代码中看到,dev-server使用的webpack配置来自build/webpack.dev.conf.js文件(测试环境下使用的是build/webpack.prod.conf.js,这里暂时不考虑测试环境)。而build/webpack.dev.conf.js中又引用了webpack.base.conf.js,所以这里我先分析webpack.base.conf.js。
webpack.base.conf.js主要完成了下面这些事情:
配置webpack编译入口
配置webpack输出路径和命名规则
配置模块resolve规则
配置不同类型模块的处理规则
说明: 这个配置里面只配置了.js、.vue、图片、字体等几类文件的处理规则,如果需要处理其他文件可以在module.rules里面另行配置。
具体请看代码注释:
build/webpack.dev.conf.js
接下来看webpack.dev.conf.js,这里面在webpack.base.conf的基础上增加完善了开发环境下面的配置,主要包括下面几件事情:
将webpack的热重载客户端代码添加到每个entry对应的应用
合并基础的webpack配置
配置样式文件的处理规则,styleLoaders
配置Source Maps
配置webpack插件
详情请看代码注释:
build/utils.js
utils提供工具函数,包括生成处理各种样式语言的loader,获取资源文件存放路径的工具函数。
- 计算资源文件存放路径
- 生成cssLoaders用于加载.vue文件中的样式
- 生成styleLoaders用于加载不在.vue文件中的单独存在的样式文件123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132var path = require('path')var config = require('../config')// extract-text-webpack-plugin可以提取bundle中的特定文本,将提取后的文本单独存放到另外的文件// 这里用来提取css样式var ExtractTextPlugin = require('extract-text-webpack-plugin')// 资源文件的存放路径exports.assetsPath = function (_path) {var assetsSubDirectory = process.env.NODE_ENV === 'production'? config.build.assetsSubDirectory: config.dev.assetsSubDirectoryreturn path.posix.join(assetsSubDirectory, _path)}// 生成css、sass、scss等各种用来编写样式的语言所对应的loader配置exports.cssLoaders = function (options) {options = options || {}// css-loader配置var cssLoader = {loader: 'css-loader',options: {// 是否最小化minimize: process.env.NODE_ENV === 'production',// 是否使用source-mapsourceMap: options.sourceMap}}// generate loader string to be used with extract text plugin// 生成各种loader配置,并且配置了extract-text-pulginfunction generateLoaders (loader, loaderOptions) {// 默认是css-loadervar loaders = [cssLoader]// 如果非css,则增加一个处理预编译语言的loader并设好相关配置属性// 例如generateLoaders('less'),这里就会push一个less-loader// less-loader先将less编译成css,然后再由css-loader去处理css// 其他sass、scss等语言也是一样的过程if (loader) {loaders.push({loader: loader + '-loader',options: Object.assign({}, loaderOptions, {sourceMap: options.sourceMap})})}// Extract CSS when that option is specified// (which is the case during production build)if (options.extract) {// 配置extract-text-plugin提取样式return ExtractTextPlugin.extract({use: loaders,fallback: 'vue-style-loader'})} else {// 无需提取样式则简单使用vue-style-loader配合各种样式loader去处理<style>里面的样式return ['vue-style-loader'].concat(loaders)}}// https://vue-loader.vuejs.org/en/configurations/extract-css.html// 得到各种不同处理样式的语言所对应的loaderreturn {css: generateLoaders(),postcss: generateLoaders(),less: generateLoaders('less'),sass: generateLoaders('sass', { indentedSyntax: true }),scss: generateLoaders('sass'),stylus: generateLoaders('stylus'),styl: generateLoaders('stylus')}}// Generate loaders for standalone style files (outside of .vue)// 生成处理单独的.css、.sass、.scss等样式文件的规则exports.styleLoaders = function (options) {var output = []var loaders = exports.cssLoaders(options)for (var extension in loaders) {var loader = loaders[extension]output.push({test: new RegExp('\\.' + extension + '$'),use: loader})}return output}build/vue-loader.conf.jsvue-loader.conf的配置比较简单,详情请看代码注释:var utils = require('./utils')var config = require('../config')var isProduction = process.env.NODE_ENV === 'production'module.exports = {// 处理.vue文件中的样式loaders: utils.cssLoaders({// 是否打开source-mapsourceMap: isProduction? config.build.productionSourceMap: config.dev.cssSourceMap,// 是否提取样式到单独的文件extract: isProduction}),transformToRequire: {video: 'src',source: 'src',img: 'src',image: 'xlink:href'}}build/dev-client.jsdev-client.js里面主要写了浏览器端代码,用于实现webpack的热更新。/* eslint-disable */// 实现浏览器端的EventSource,用于跟服务器双向通信// webpack热重载客户端跟dev-server上的热重载插件之间需要进行双向通信// 服务端webpack重新编译后,会向客户端推送信息,告诉客户端进行更新require('eventsource-polyfill')// webpack热重载客户端var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')// 客户端收到更新动作,执行页面刷新hotClient.subscribe(function (event) {if (event.action === 'reload') {window.location.reload()}})
build/build.js
讲完了开发环境下的配置,下面开始来看构建环境下的配置。执行”npm run build”的时候首先执行的是build/build.js文件,build.js主要完成下面几件事:
loading动画
删除目标文件夹
执行webpack构建
输出信息
说明: webpack编译之后会输出到配置里面指定的目标文件夹;删除目标文件夹之后再创建是为了去除旧的内容,以免产生不可预测的影响。
详情请看代码注释:
build/webpack.prod.conf.js
构建的时候用到的webpack配置来自webpack.prod.conf.js,该配置同样是在webpack.base.conf基础上的进一步完善。主要完成下面几件事情:
合并基础的webpack配置
配置样式文件的处理规则,styleLoaders
配置webpack的输出
配置webpack插件
gzip模式下的webpack插件配置
webpack-bundle分析
说明: webpack插件里面多了丑化压缩代码以及抽离css文件等插件。
详情请看代码:
四、config文件夹分析
config/index.js
config文件夹下最主要的文件就是index.js了,在这里面描述了开发和构建两种环境下的配置,前面的build文件夹下也有不少文件引用了index.js里面的配置。下面是代码注释:
config/dev.env.js、config/prod.env.js和config/test.env.js
这三个文件就简单设置了环境变量而已,没什么特别的。
五、总结
到这里对模板项目的build和config文件夹下面的内容已经基本了解,知道了在实际使用中根据自己的需求修改哪里的配置,例如,当我有需要配置代理的时候要在config/index.js里面的dev.proxyTable设置,当我修改了资源文件夹名称static同样需要在config/index.js里面设置。webpack的插件好多,在看代码的过程中遇到不认识的插件都是要去查看很多文档(github,npm或者博客),感觉实际过程中更改插件配置或者使用新插件也是需要费点心思钻文档和网上其他博客介绍