构建方式篇|博客系列
# 一、几种开发工具
每次要编译代码时,手动运行 npm run build 就会变得很麻烦。
不知道你有没有使用过类似于
vue-cli这样的脚手架工具, 在使用它们的时候, 每次只要执行npm run start这样的指令就可以创建一个本地的web服务器, 然后打开一个例如localhost:8080这样的端口页面, 同时还有热更新等功能.
其实这些功能的实现都是vue-cli内部使用了webpack.
webpack中有几个不同的选项,可以帮助你在代码发生变化后自动编译代码.
# webpack’s Watch Mode(观察者模式)
观察者模式, 只需要在package.json里配置一个脚本命令:
"scripts": {
"watch": "webpack --watch"
}
使用npm run watch命令之后, 会看到编译过程, 但是不会退出命令行, 而是实时监控文件.
比如你在重新修改了本地的代码并保存后, 它会重新进行编译, 不需要我们手动再执行编译指令, 缺点是你需要手动刷新页面才能看到更改效果.
(--watch也可以简写为-w)
# webpack-dev-server
使用webpack-dev-server会为你提供一个简单的web服务器, 它的作用就是监听文件的改变并自动编译, 同时会自动刷新页面. 比观察者模式厉害.
使用步骤:
- 安装:
$ npm i --save-dev webpack-dev-server - 添加脚本命令:
"start": "webpack-dev-server --open"
使用此指令效果:
不会生成dist文件夹, 而是开启了一个本地的web服务器localhost:8080
每次修改了本地代码之后, 都会重新自动编译, 并刷新页面
其它配置项:
webpack-dev-server也有很多配置项能在webpack.config.js中配置
只需要在devServer里进行配置, 例如:
module.exports = {
devServer: {
contentBase: './dist', // 告诉服务器从哪里提供内容
host: '0.0.0.0', // 默认是 localhost
port: 8000, // 端口号, 默认是8080
open: true, // 是否自动打开浏览器
hot: true, // 启用 webpack 的模块热替换特性
hotOnly: true // 当编译失败之后不进行热更新
}
}
如果你使用了这个功能之后, 你就会发现, 它就有点vue-cli的样子了.
更多关于devServer的配置可以查看这里: 开发中Server。
# webpack-dev-middleware
# 基本使用
webpack-dev-middleware 是一个容器(wrapper),它可以把 webpack 处理后的文件传递给一个服务器(server)。
webpack-dev-server 能够开启一个本地的web服务器, 就是因为在内部使用了它,但是, 它也可以作为一个包来单独使用.
这里我就以官方的案例来进行讲解.
使用webpack-dev-middleware配合express server来介绍它的功能.
(express是一个很精简的Node.js开发框架,如果你之前没用过也没关系,使用起来很简单。)
先来说下我的需求, 我想要实现一个这个功能:
- 配置一条
script指令让它能运行一个本地web服务器(也就是能够在localhost: 3000中查看页面) - 每次修改本地代码能够重新编译
- 但是不会自动刷新页面
- 安装所需的依赖:
$ npm i --save-dev webpack-dev-middleware express
- 在项目的根目录下创建一个
server.js文件用来编写本地服务:
// server.js
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const app = express()
const config = require('./webpack.config')
const compiler = webpack(config)
// 把 webpack 处理后的文件传递给一个服务器
app.use(webpackDevMiddleware(compiler))
app.listen(3000, function() {
console.log('Example app listening on port 3000!\n');
})
- 在
package.json里配置指令运行server.js:
{
"scripts": {
"server": "node server.js"
}
}
# publicPath配置项
在学习这里的时候, 我顺便也了解到了webpack.config.js 中output的另一个属性publicPath.
开始看文档 output.outputPath的时候没太看懂.
后来我结合webpack-dev-middleware来试了一下它.
首先修改一下webpack.config.js的配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
devtool: 'inline-source-map', // 仅开发环境报错追踪
plugins: [
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ['dist']
}),
new HtmlWebpackPlugin({
title: 'Webpack Output2',
filename: 'index.html',
template: 'src/index.html'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
+ publicPath: '/assets/'
}
}
然后修改一下server.js:
// server.js
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const app = express()
const config = require('./webpack.config')
const compiler = webpack(config)
// 把webpack 处理后的文件传递给一个服务器
app.use(webpackDevMiddleware(compiler
+ ,{
+ publicPath: config.output.publicPath
+ }
))
app.listen(3000, function() {
console.log('Example app listening on port 3000!\n');
})
保存上面👆两个文件, 然后重新执行npm run server, 打开localhost:3000 会发现页面显示的是:
Cannot GET /
你需要打开localhost:3000/assets/才能看到正确的页面.
并且如果项目里有对资源的引用的话, 也会自动加上publicPath的前缀:
icon.png => 变为 /assets/icon.png
此选项指定在浏览器中所引用的「此输出目录对应的公开 URL」。
注⚠️:
如果没有配置output.publicPath和webpack-dev-middleware的publicPath, 则默认都会是"",以根目录作为配置项。
如果配置了output.publicPath, 则webpack-dev-middleware中的publicPath也要和它一样才行。
# 二、不同环境的构建
开发环境和生产环境的构建目标差异是非常大的.
- 开发环境中, 我们可能有实时重新加载(live reloading) 、热模块替换(hot module replacement)等能力
- 生产环境中, 我们更加关注更小的bundle(压缩输出), 更轻量的source map, 还有更优化的资源等.
所以为了遵循逻辑分离, 我们可以为每个环境编写彼此独立的webpack配置.
虽说是想要编写各自独立的配置, 但是肯定也有一些公用的配置项, 我们可以将这些公用的配置项提取出来, 然后不同的配置写在不同的文件中.
(第二节教材案例GitHub地址: LinDaidai/webpack-example/webpak-merge ⚠️:请仔细查看README说明)
# webpack-merge
最终, 为了将这些配置项合并在一起, 我们需要用到webpack-merge工具.
首先安装这个工具:
$ npm i --save-dev webpack-merge
然后让我们将原本的webpack.config.js拆开, 编写成三个不同的webpack配置文件:
webpack-demo
|- package.json
- |- webpack.config.js
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
|- /dist
|- /src
|- index.js
|- math.js
|- /node_modules
webpack.common.js:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'webpack bundle'
})
]
}
webpack.dev.js:
← 基础篇自定义plugin篇 →
