从package.json 中可以看出,npm run build,其实是执行了 node build/build.js,我们在build文件夹中找到build.js,build主要的工作是:检测node和npm版本,删除dist包,webpack构建打包,在终端输出构建信息并结束,如果报错,则输出报错信息。
'use strict'
require(
'./check-versions')()
process.
env.NODE_ENV
=
'production'
const ora
=
require(
'ora')
// 在终端显示的旋转器插件
const rm
=
require(
'rimraf')
// 用于删除文件夹
const path
=
require(
'path')
const chalk
=
require(
'chalk')
// 终端文字颜色插件
const webpack
=
require(
'webpack')
const config
=
require(
'../config')
const webpackConfig
=
require(
'./webpack.prod.conf')
const spinner
=
ora(
'building for production...')
spinner.
start()
// 删除dist文件夹,之后webpack打包
rm(
path.
join(
config.
build.
assetsRoot,
config.
build.
assetsSubDirectory),
err
=> {
if (err)
throw err
webpack(webpackConfig, (
err,
stats)
=> {
spinner.
stop()
if (err)
throw err
process.
stdout.
write(
stats.
toString({
colors:
true,
modules:
false,
children:
false,
// If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks:
false,
chunkModules:
false
})
+
'
\n\n
')
if (
stats.
hasErrors()) {
console.
log(
chalk.
red(
' Build failed with errors.
\n
'))
process.
exit(
1)
}
console.
log(
chalk.
cyan(
' Build complete.
\n
'))
console.
log(
chalk.
yellow(
' Tip: built files are meant to be served over an HTTP server.
\n
'
+
' Opening index.html over file:// won
\'
t work.
\n
'
))
})
})
build.js用到了webpack.prod.conf.js,他与webpack.base.conf.js merge之后,作为webpack配置文件,我们再看看webpack.prod.conf.js,主要做的工作是:
1.提取webpack生成的bundle中的文本,到特定的文件,使得css,js文件与webpack输出的bundle分离。
2.合并基本的webpack配置
3.配置webpack的输出,包括输出路径,文件名格式。
4.配置webpack插件,包括丑化代码。
5.gzip下引入compression插件进行压缩。
'use strict'
const path
=
require(
'path')
const utils
=
require(
'./utils')
const webpack
=
require(
'webpack')
const config
=
require(
'../config')
const merge
=
require(
'webpack-merge')
const baseWebpackConfig
=
require(
'./webpack.base.conf')
const CopyWebpackPlugin
=
require(
'copy-webpack-plugin')
const HtmlWebpackPlugin
=
require(
'html-webpack-plugin')
// 用于从webpack生成的bundle中提取文本到特定文件中的插件
// 可以抽取出css,js文件将其与webpack输出的bundle分离
const ExtractTextPlugin
=
require(
'extract-text-webpack-plugin')
const OptimizeCSSPlugin
=
require(
'optimize-css-assets-webpack-plugin')
const UglifyJsPlugin
=
require(
'uglifyjs-webpack-plugin')
const env
=
process.
env.NODE_ENV
===
'testing'
?
require(
'../config/test.env')
:
require(
'../config/prod.env')
// 合并基础的webpack配置
const webpackConfig
=
merge(baseWebpackConfig, {
module: {
rules:
utils.
styleLoaders({
sourceMap:
config.
build.
productionSourceMap,
extract:
true,
usePostCSS:
true
})
},
devtool:
config.
build.
productionSourceMap
?
config.
build.
devtool
:
false,
// 配置webpack输出的目录,及文件命名规则
output: {
path:
config.
build.
assetsRoot,
filename:
utils.
assetsPath(
"js/[name].[chunkhash].js"),
chunkFilename:
utils.
assetsPath(
"js/[id].[chunkhash].js")
},
plugins: [
// webpack插件配置
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new
webpack.
DefinePlugin({
"process.env": env
}),
// 丑化代码
new
UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings:
false
}
},
sourceMap:
config.
build.
productionSourceMap,
parallel:
true
}),
// // 抽离css文件到单独的文件
new
ExtractTextPlugin({
filename:
utils.
assetsPath(
"css/[name].[contenthash].css"),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks:
true
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new
OptimizeCSSPlugin({
cssProcessorOptions:
config.
build.
productionSourceMap
? { safe:
true, map: { inline:
false } }
: { safe:
true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new
HtmlWebpackPlugin({
// 生成并注入index.html
filename:
process.
env.NODE_ENV
===
"testing"
?
"index.html"
:
config.
build.
index,
template:
"index.html",
inject:
true,
minify: {
removeComments:
true,
collapseWhitespace:
true,
removeAttributeQuotes:
true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode:
"dependency"
}),
// keep module.id stable when vendor modules does not change
new
webpack.
HashedModuleIdsPlugin(),
// enable scope hoisting
new
webpack.
optimize.
ModuleConcatenationPlugin(),
// split vendor js into its own file
new
webpack.
optimize.
CommonsChunkPlugin({
name:
"vendor",
minChunks(
module) {
// 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",
minChunks:
Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new
webpack.
optimize.
CommonsChunkPlugin({
name:
"app",
async:
"vendor-async",
children:
true,
minChunks:
3
}),
// copy custom static assets
new
CopyWebpackPlugin([
{
from:
path.
resolve(
__dirname,
"../static"),
to:
config.
build.
assetsSubDirectory,
ignore: [
".*"]
}
])
]
});
// gzip模式下需要引入compression插件进行压缩
if (
config.
build.
productionGzip) {
const CompressionWebpackPlugin
=
require(
'compression-webpack-plugin')
webpackConfig.
plugins.
push(
new
CompressionWebpackPlugin({
asset:
'[path].gz[query]',
algorithm:
'gzip',
test:
new
RegExp(
'
\\
.('
+
config.
build.
productionGzipExtensions.
join(
'|')
+
')$'
),
threshold:
10240,
minRatio:
0.8
})
)
}
if (
config.
build.
bundleAnalyzerReport) {
const BundleAnalyzerPlugin
=
require(
'webpack-bundle-analyzer').
BundleAnalyzerPlugin
webpackConfig.
plugins.
push(
new
BundleAnalyzerPlugin())
}
module.
exports
= webpackConfig
总结:执行npm run dev或者npm run start,实际是在node环境执行build/dev-server.js, dev-server.js会去拿到config中的端口等配置,通过express起一个服务,通过插件自动打开浏览器,加载webpack编译后放在内存的bundle。
执行npm run build,实际上执行了build/build.js,通过webpack的一系列配置及插件,将文件打包合并丑化,并创建dist目录,放置编译打包后的文件,这将是未来用在生产环境的包。