版本号
- vue-cli 2.8.1 (终端通过vue -V 可查看)
- vue 2.2.2
- webpack 2.2.1
目录结构
webpack配置
主要对build目录下的webpack配置做详细分析
webpack.base.conf.js
入口文件entry
config的配置在config/index.js文件中
文件解析resolve
主要设置模块如何被解析。
模块解析module
如何处理项目不同类型的模块。
注: 关于query 仅由于兼容性原因而存在。请使用 options 代替。
webpack.dev.conf.js
开发环境下的webpack配置,通过merge方法合并webpack.base.conf.js基础配置
模块配置
在util.styleLoaders中的配置如下
上面的代码中调用了exports.cssLoaders(options),用来返回针对各类型的样式文件的处理方式,具体实现如下
loader: 'css-loader',options: { //options是loader的选项配置
minimize: process.env.NODE_ENV === 'production',//生成环境下压缩文件
sourceMap: options.sourceMap //根据参数是否生成sourceMap文件
}
}
function generateLoaders (loader,loaderOptions) { //生成loader
var loaders = [cssLoader] // 默认是css-loader
if (loader) { // 如果参数loader存在
loaders.push({
loader: loader + '-loader',options: Object.assign({},loaderOptions,{ //将loaderOptions和sourceMap组成一个对象
sourceMap: options.sourceMap
})
})
}
if (options.extract) { // 如果传入的options存在extract且为true
return ExtractTextPlugin.extract({ //ExtractTextPlugin分离js中引入的css文件
use: loaders,//处理的loader
fallback: 'vue-style-loader' //没有被提取分离时使用的loader
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
return { //返回css类型对应的loader组成的对象 generateLoaders()来生成loader
css: generateLoaders(),postcss: generateLoaders(),less: generateLoaders('less'),sass: generateLoaders('sass',{ indentedSyntax: true }),scss: generateLoaders('sass'),stylus: generateLoaders('stylus'),styl: generateLoaders('stylus')
}
}
插件配置
webpack.prod.conf.js
生产环境下的webpack配置,通过merge方法合并webpack.base.conf.js基础配置
module的处理,主要是针对css的处理
同样的此处调用了utils.styleLoaders
插件plugins
额外配置
//引入压缩文件的组件,该插件会对生成的文件进行压缩,生成一个.gz文件
var CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',//目标文件名
algorithm: 'gzip',//使用gzip压缩
test: new RegExp( //满足正则表达式的文件会被压缩
'\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),threshold: 10240,//资源文件大于10240B=10kB时会被压缩
minRatio: 0.8 //最小压缩比达到0.8时才会被压缩
})
)
}
npm run dev
有了上面的配置之后,下面看看运行命令npm run dev
发生了什么
在package.json文件中定义了dev运行的脚本
当运行npm run dev命令时,实际上会运行dev-server.js文件
该文件以express作为后端框架
var autoOpenBrowser = !!config.dev.autoOpenBrowser //是否自动打开浏览器
var proxyTable = config.dev.proxyTable //http的代理url
var app = express() //启动express
var compiler = webpack(webpackConfig) //webpack编译
//webpack-dev-middleware的作用
//1.将编译后的生成的静态文件放在内存中,所以在npm run dev后磁盘上不会生成文件
//2.当文件改变时,会自动编译。
//3.当在编译过程中请求某个资源时,webpack-dev-server不会让这个请求失败,而是会一直阻塞它,直到webpack编译完毕
var devMiddleware = require('webpack-dev-middleware')(compiler,{
publicPath: webpackConfig.output.publicPath,quiet: true
})
//webpack-hot-middleware的作用就是实现浏览器的无刷新更新
var hotMiddleware = require('webpack-hot-middleware')(compiler,{
log: () => {}
})
//声明hotMiddleware无刷新更新的时机:html-webpack-plugin 的template更改之后
compiler.plugin('compilation',function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit',function (data,cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
//将代理请求的配置应用到express服务上
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context,options))
})
//使用connect-history-api-fallback匹配资源
//如果不匹配就可以重定向到指定地址
app.use(require('connect-history-api-fallback')())
// 应用devMiddleware中间件
app.use(devMiddleware)
// 应用hotMiddleware中间件
app.use(hotMiddleware)
// 配置express静态资源目录
var staticPath = path.posix.join(config.dev.assetsPublicPath,config.dev.assetsSubDirectory)
app.use(staticPath,express.static('./static'))
var uri = 'http://localhost:' + port
//编译成功后打印uri
devMiddleware.waitUntilValid(function () {
console.log('> Listening at ' + uri + '\n')
})
//启动express服务
module.exports = app.listen(port,function (err) {
if (err) {
console.log(err)
return
}
// 满足条件则自动打开浏览器
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
})
npm run build
由于package.json中的配置,运行此命令后会执行build.js文件
var spinner = ora('building for production...')
spinner.start()
// 删除已编译文件
rm(path.join(config.build.assetsRoot,config.build.assetsSubDirectory),err => {
if (err) throw err
//在删除完成的回调函数中开始编译
webpack(webpackConfig,function (err,stats) {
spinner.stop() //停止loading
if (err) throw err
// 在编译完成的回调函数中,在终端输出编译的文件
process.stdout.write(stats.toString({
colors: true,modules: false,children: false,chunks: false,chunkModules: false
}) + '\n\n')
})
})