上一篇:從vue-cli學(xué)webpack配置--針對(duì)webpack2
現(xiàn)在大家用vue-cli工具新建的webpack工程應(yīng)該是基于webpack3,與上一篇的不同之處在于它不在是用webpack-dev-middleware、webpack-hot-middleware來(lái)做熱更新的,而是直接用webpack-dev-server,當(dāng)然整個(gè)配置更加的簡(jiǎn)潔了。生產(chǎn)環(huán)境構(gòu)建的配置與上一篇的區(qū)別是一致,我們直接看開(kāi)發(fā)環(huán)境。
第一部分 webpack-dev-server基礎(chǔ)使用
webpack-dev-server是一個(gè)小型node express 服務(wù),它是一個(gè)獨(dú)立的npm包,npm install webpack-dev-server 后,你就可以通過(guò)命令啟動(dòng)它。
基礎(chǔ)命令:
webpack-dev-server --inline --process --config build/webpack.dev.conf.js
/* inline
dev-server有兩種模式,一種是iframe模式,一種是inline模式。
iframe模式,訪問(wèn)時(shí)需要 http://host:port/webpack-dev-server/path,加多一個(gè)webpack-dev-server,而inline則不用,推薦用inline
progress :將運(yùn)行進(jìn)度輸出到控制臺(tái)
config: 指定配置文件
*/
然后我們看到package.json 也是這樣啟動(dòng)服務(wù)的:

那我們就看build/webpack.dev.conf.js:
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
// 這里同樣也是合并基本的配置,加入開(kāi)發(fā)環(huán)境的配置
// 指定devServer
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool, //指定生成那種形式的souceMap,cheap-module-eval-source-map這個(gè)是適合開(kāi)發(fā)環(huán)境
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning', // 客戶端報(bào)錯(cuò)等級(jí)
historyApiFallback: { // 當(dāng)使用 HTML5 History API 時(shí),下面匹配的路徑,出現(xiàn)404 響應(yīng)都可能需要被替代為 index.html
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true, //啟用熱部署
contentBase: false, //告訴服務(wù)觀察對(duì)應(yīng)目錄文件更改情況,文件更改后,會(huì)觸發(fā)重新加載;這里為false // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host, // 指定可以訪問(wèn)的主機(jī)地址,默認(rèn)是localhost,允許外網(wǎng)范圍則是0.0.0.0
port: PORT || config.dev.port, // 端口
open: config.dev.autoOpenBrowser, // 是否自動(dòng)打開(kāi)瀏覽器
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false, // 當(dāng)出現(xiàn)編譯器錯(cuò)誤或警告時(shí),在瀏覽器中顯示全屏疊加,其實(shí)就是我們經(jīng)??吹降哪莻€(gè)報(bào)錯(cuò)頁(yè)面
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin //啟用 quiet 后,除了初始啟動(dòng)信息之外的任何內(nèi)容都不會(huì)被打印到控制臺(tái)
watchOptions: { // webpack 使用文件系統(tǒng)(file system)獲取文件改動(dòng)的通知,一些情況下不生效,所有采用輪詢
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})
這里實(shí)際上也是合并基礎(chǔ)webpack配置,最后resolve出去。當(dāng)我們通過(guò)命令行調(diào)動(dòng)的webpack-dev-server,指定它的config的時(shí)候,程序?yàn)槲覀兗虞d這個(gè)配置,提供給webpack-dev-server使用,這個(gè)dev-server是使用webpack幫我們打包,打包的東西不是輸出到dist而是存在內(nèi)存中。這個(gè)有兩個(gè)注意點(diǎn):
1、靜態(tài)資源更新怎么檢測(cè)到:
A 是 contentbase指定目錄,進(jìn)行檢測(cè),然后我們?nèi)ナ謩?dòng)更新目錄的下的靜態(tài)資源
B vue-cli工程使用CopyWebpackPlugin,同時(shí)啟動(dòng)hot熱部署,當(dāng)我們更改靜態(tài)資源,CopyWebpackPlugin會(huì)幫我們復(fù)制過(guò)去,所以我們不需要手動(dòng)去更改發(fā)布目錄的下的靜態(tài)資源,而且也不需要dev-server去幫我們檢測(cè)發(fā)布目錄的靜態(tài)資源
2、webpack-dev-server是如何實(shí)現(xiàn)熱替換
這點(diǎn)我在官網(wǎng)上找到答案:

官網(wǎng)的意思就是說(shuō),如果你啟動(dòng)了dev-server配置中的hot,那你需要搭配webpack.HotModuleReplacementPlugin, 這個(gè)插件是用來(lái)實(shí)現(xiàn)HRM,而且這個(gè)插件會(huì)有dev-server或者webpack自動(dòng)調(diào)用,以實(shí)現(xiàn)熱更新。
最后啰嗦幾句,為啥是用portfinder? 這個(gè)是一個(gè)檢查當(dāng)前機(jī)器開(kāi)放端口的工具,因?yàn)槲覀儐?dòng)的時(shí)候會(huì)幫我們看是否端口沖突,沖突則報(bào)錯(cuò),不沖突這程序繼續(xù),暴露我們配置給調(diào)用我們的命令行進(jìn)程。
整體webpack-dev-server的配置比上一篇使用node express服務(wù),搭配webpck-dev-middleware和webpack-hot-middleware來(lái)實(shí)現(xiàn)熱更新要來(lái)得簡(jiǎn)潔多。不過(guò)實(shí)際中,dev-server也是一樣的,只不過(guò)人家?guī)湍闩昧T了。但是配置更清晰易懂。
系列文章:
《什么是構(gòu)建? webpack打包思想?》
《webpack基礎(chǔ)使用》
《從vue-cli學(xué)webpack配置1——針對(duì)webpack2》
《從vue-cli學(xué)webpack配置2——針對(duì)webpack3》
《webpack 、mainfest 、runtime 、緩存與CommonsChunkPlugin》
《webpack打包慢的解決方案》