Simple summary of webpack configuration in vue-cli
webpack introduction
With the arrival of the wave of mobile connectivity, Webapp patterns, SPA are getting more and more attention. How to organize fragmented, multi-format code and resources in a development environment and ensure that they load and update quickly and elegantly on the browser side requires a modular system. Webpack is such a modular system. It has several features:
- Chunked transfers, lazy loading on demand;
- Resources in various formats are JavaScript modules that can be loaded with
require;
Specifically, Webpack configuration consists of these main areas:
- Entry: specifies the entry point to our code. Its value is either a string or an object (multiple entries).
- loader: because Webpack itself can only handle JavaScript modules, if you want to handle other types of files, you need to use a loader (loader) for conversion. The loader converts resources into JavaScript modules, providing preprocessing before packaging.
- Plugins: provide additional extensions that the loader cannot do.
- Export: includes the path where the packaged files are placed and their filenames.
vue-cli version
2.8.1 (ESLint not used, unit tests not installed, e2e tests)
Directory of related configuration files
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
├── ...
├── build
│ ├── build.js
│ ├── check-versions.js
│ ├── dev-client.js
│ ├── dev-server.js
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── ...
├── package.json
└── ...
package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
// ...
"scripts": {
// 开发环境
"dev": "node build/dev-server.js",
// 生产环境
"build": "node build/build.js"
},
// ...
"devDependencies": {
// ...
// 配置分离,将配置定义在config/下,然后合并成最终的配置,以避免webpack.config.js臃肿
"webpack-merge": "^2.6.1"
},
// ...
}
Basic configuration
config/index.js
In this file is the base configuration of webpack, describing the two configurations for the development and production environments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// see https://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
module.exports = {
// 生产环境
build: {
env: require('./prod.env'), // 编译环境
index: path.resolve(__dirname, '../dist/index.html'), // 输入的文件
assetsRoot: path.resolve(__dirname, '../dist'), // 本地系统上的路径,输出的目标文件夹
assetsSubDirectory: 'static', // 输出的二级文件夹(自动生成)
assetsPublicPath: '/', // 发布资源的根目录,可配置为资源服务器url
productionSourceMap: true, // 记录文件压缩前后的位置信息
// 压缩 gzip模式下需要压缩的文件的扩展名
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
// 开发环境
dev: {
env: require('./dev.env'),
port: 8080, // 监听的端口
autoOpenBrowser: true, // 自动打开浏览器
assetsSubDirectory: 'static', // 输出的二级文件夹(自动生成)
assetsPublicPath: '/', // 发布资源的根目录,可配置为资源服务器url
// 如设置"/api": "https://localhost:3000",则请求到 /api/users 现在会被代理到请求 https://localhost:3000/api/users
// 需要proxyTable代理的接口(可跨域)
proxyTable: {},
// 记录文件压缩前后的位置信息
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}
build/webpack.base.conf.js
This file is the basic configuration that is used in both development and production environments. webpack.dev.conf.js is introduced in dev-server.js, webpack.prod.conf.js is introduced in build.js, and webpack.dev.conf.js and webpack.prod.conf.js are introduced in both files (webpack.dev.conf.js and webpack.prod.conf.js). .base.conf.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
// [[ 1. 配置webpack编译入口 ]]
entry: {
app: './src/main.js'
},
// [[ 2. 配置webpack输出路径和命名规则 ]]
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
// [[ 3. 配置模块resolve规则 ]]
resolve: {
extensions: ['.js', '.vue', '.json'],
// 创建路径别名
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
},
// [[ 4. 配置不同类型模块的处理规则 ]]
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
Development environment
build/dev-server.js
Execute npm run dev to first run the file dev-server.js.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// [[ 1. 检查node和npm的版本 ]]
require('./check-versions')()
// [[ 2. 引入相关插件和配置 ]]
// 获取配置,获取配置中设置的环境变量
var config = require('../config')
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn') // 用于打开默认浏览器打开localhost:端口
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware') // 一个express中间件,用于将http请求代理到其他服务器
var webpackConfig = require('./webpack.dev.conf')
// 设置监听端口
var port = process.env.PORT || config.dev.port
// 设置是否自动打开浏览器
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// 定义HTTP代理表
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable
// [[ 3. 创建express服务器和webpack编译器 ]]
var app = express()
var compiler = webpack(webpackConfig)
// [[ 4. 配置开发中间件和热重载中间件 ]]
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
})
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {}
})
// 当html-webpack-plugin模版文件发生改变,强制页面重载
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// [[ 5. 挂载代理服务和中间件 ]]
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
// 重定向不存在的URL
app.use(require('connect-history-api-fallback')())
// 使用开发中间件,即把webpack编译后输出到内存中的文件资源挂到express服务器上
app.use(devMiddleware)
// 挂载热重载
app.use(hotMiddleware)
// [[ 6. 配置静态资源 ]]
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
// [[ 7. 启动服务器监听特定端口]]
var uri = 'https://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
// [[ 8. 打开默认浏览器打开localhost:端口 ]]
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})
// 监听端口
var server = app.listen(port)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}
Other configuration files
- build/webpack.dev.conf.js: on the basis of webpack.base.conf to improve the development environment needs to configure, such as merging configuration files, more friendly output webpack warning messages and so on
- build/utils.js: configure static resources path, pei z style loaders cssLoaders and styleLoaders
- build/vue.loader.conf.js: configure the css loader and compile css after automatically add the prefix (autoprefixer)
Production environment
build/build.js
Executing npm run build first runs the file build.js.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// [[ 1. 检查NodeJS和npm的版本 ]]
require('./check-versions')()
process.env.NODE_ENV = 'production'
var ora = require('ora') // 用于开启loading动画
var rm = require('rimraf')
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')
// [[ 2. 开启loading动画 ]]
var spinner = ora('building for production...')
spinner.start()
// [[ 3. 删除创建打包的目标文件夹]]
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
// [[ 4. webpack编译 ]]
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
// 输出相关信息
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
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'
))
})
})
Other configuration files
- build/webpack.prod.conf.js: on the basis of webpack.base.conf to improve the production environment needs to be configured, such as merging the base webpack configuration, configure the output of webpack, ugly compression of code, abstraction of css files, etc.
Reference
Off-topic
The commenting system has been switched to Gitment, which has been getting quite a bit of attention lately, and it seems awesome so far ^ ^