上一篇 《webpack基礎(chǔ)使用》
前言:webpack的配置其實(shí)挺多巷帝,而且更多的是體現(xiàn)在loader和plugin方面的配置扫夜,上篇我們只是簡單介紹webpack基礎(chǔ)使用,因?yàn)槲矣X得更多細(xì)節(jié)方面可以在vue-cli生成的工程中學(xué)習(xí)到现拒。大家現(xiàn)在用工具生成出來的是基于webpack 3x版本的望侈,比2x版本的配置更簡潔清晰,不同點(diǎn)是:2x版本的用了webpack-dev-middle和webpack-hot-middleware插件提供模塊熱更新侥猬,而3x版本的配置則是用webpack-dev-server捐韩;其實(shí)兩者有好有壞荤胁,當(dāng)然相比之下,我覺得webpack-dev-server會(huì)更直接點(diǎn)。
vue-cli的使用
//vue-cli工具很簡單,命令行里:
npm install vue-cli -g
// 安裝完之后垢油,就有vue命令了
vue init webpack vue-webpack2 // 初始化一個(gè)webpack工程滩愁,工程名字為vue-webpack2
//下面圖片中,eslint那一行選擇了yes廉丽,eslint是用于管理代碼格式的妻味,良好的編碼格式是很重要,unit test 和nigtht watch 就選擇no蔑匣,因?yàn)檫@次我們主要是研究webpack配置哈
命令執(zhí)行完后,在當(dāng)前目錄下就會(huì)看到新的文件夾凿将,也就是你的工程vue-webpack2(現(xiàn)在vue-cli出來的工程是基于webpack3的牧抵, 我給大家提供一個(gè)webpack2配置的版本,下一篇文章里再講基于webpack3)妹孙。
目錄結(jié)構(gòu):
src:放我們自己代碼
build和config:webpack配置获枝,我們學(xué)習(xí)的重點(diǎn)
其他配置文件:稍后講
第一部分:非重點(diǎn)但注意的配置文件
.editorconfig文件
這個(gè)文件主要是對編輯器的編輯做設(shè)置省店,里面主要設(shè)置一個(gè)tab縮進(jìn)多少個(gè)空格,換行符(linux系統(tǒng)的是lf雹舀, window系統(tǒng)則是ctlf)说榆,還有編碼設(shè)置等。這個(gè)文件生效需要你安裝editorconfig插件串慰,這個(gè)插件支持眾多ide編輯器荠卷,像sublime、vscode掂碱、eclipse慎冤,主要是為了統(tǒng)一編輯蚁堤,使得我們的js能夠運(yùn)行到其他操作系統(tǒng)。(為什么java不需要撬即,因?yàn)閖vm虛擬機(jī)最終執(zhí)行的java文件編譯后的二進(jìn)制.class文件呈队,不同平臺有不同jvm宪摧,所以java是跨平臺的)
.eslintrc.js
eslint是用于統(tǒng)一團(tuán)隊(duì)之間的編碼風(fēng)格的工具,以前看過一些老代碼蕊苗,風(fēng)格不統(tǒng)一沿彭,看起來很痛苦膝蜈。有些人是分號黨,有些人卻不是非剃。eslint對換行推沸、空格等都可以配置一套規(guī)則,團(tuán)隊(duì)里基于這套規(guī)則寫出的代碼肺素,在閱讀性就做到了統(tǒng)一倍靡。大家可以參考https://eslint.org/了解其詳細(xì)的配置。上手很容易他挎,npm install eslint 然后捡需,eslint src/main.js ,工具就根據(jù).eslintrc.js配置開始檢查main.js站辉。這種用法比較初級,我們可以看一下我們的工程里是怎么使用的殊霞。
package.json
這個(gè)就不用說了吧汰蓉,我們可以了解一下npm script的使用技巧古沥,看下圖
工程里給我們配置了四個(gè)任務(wù)娇跟,所以你就可以執(zhí)行npm run dev 或者執(zhí)行npm run build 苞俘,以及npm run lint。
比如 npm run lint 乞封,實(shí)際執(zhí)行的就是對應(yīng)的: eslint --ext .js, .vue src 這個(gè)就是告訴eslint幫我們檢查src下面的js文件和vue文件岗憋。另外你也可以添加配置:
"test": "npm run lint & npm run dev"
當(dāng)你執(zhí)行npm run test 就會(huì)執(zhí)行npm run lint后再執(zhí)行 npm run dev
--其他文件仔戈,下面講webpack配置會(huì)講到拧廊,好進(jìn)入第二部分--
第二部分: webpack配置()
bulid目錄下的webpack.base.conf.js
var path = require('path') // node path模塊
var utils = require('./utils')
var config = require('../config') // config目錄吧碾,vue-cli工程分成兩個(gè)環(huán)境倦春,一個(gè)是開發(fā)的dev環(huán)境落剪,一個(gè)是生產(chǎn)環(huán)境production
var vueLoaderConfig = require('./vue-loader.conf') // 引入vue-loader的配置,vue-loader是處理.vue文件使用的
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
},
module: { // 定義對文件的處理loader
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: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
這個(gè)文件定義webpack的基礎(chǔ)配置:
引入config:對應(yīng)config目錄的index.js: 這個(gè)主要是為區(qū)分開發(fā)環(huán)境與生產(chǎn)環(huán)境的不同,比如開發(fā)環(huán)境是本機(jī)測試的暮胧,那么我的publicPath設(shè)置為空问麸,但是生產(chǎn)環(huán)境則設(shè)置aliyu.cdn.com严卖,所以output里面的publicPath根據(jù)process.env.NODE_ENV 是否為開發(fā)環(huán)境,引用config對應(yīng)的屬性来颤。比如開發(fā)環(huán)境引入圖片的url是<img src='/pic.jpg'>,而生產(chǎn)環(huán)境則是<img src='http://aliyun.cdn.com/pic.jpg'>稠肘。這就是output的publicPath的作用项阴,設(shè)置config就是為了區(qū)分開發(fā)環(huán)境還是生產(chǎn)環(huán)境。
resolve:
extentions: 配置這個(gè)參數(shù)后略荡,可以省略擴(kuò)展名歉胶。如:import * from 'test.js' 可以寫成 import * from 'test'
alias: 重命名跨扮。路徑上的重命名验毡,比如你要import一個(gè)模塊晶通,路徑是D://project/vue-webapck2/src/modules/car 寫完整路徑很長很累哟玷,工程中配置了,我們可以寫成 @/modules/car
下面則是對文件處理定義了loader:
loader是定義在module.rules中喉脖,其實(shí)意思就是對模塊文件的處理規(guī)則树叽。因?yàn)閣ebpack把每個(gè)一個(gè)文件谦絮,哪怕是圖片視頻都當(dāng)成一個(gè)模塊层皱,只不過它識別不了需要這loader處理工具來幫助它。
test:正則匹配草冈,匹配.vue文件用vue-loader處理瓮增,.js用babel-loader處理
loader: 指定處理的loader工具
options: loader怎么處理文件也需要你設(shè)置參數(shù)绷跑,你可以用個(gè)options傳遞你設(shè)置的參數(shù)給它
bable-loader: 對js文件做處理,這樣我們可以用es6、es7規(guī)范來寫js带膜,babel-loader會(huì)根據(jù)項(xiàng)目根目錄下的.bablerc文件的配置對于你的js代碼進(jìn)行轉(zhuǎn)義鸳谜,有些瀏覽器沒有實(shí)現(xiàn)es6 或者es7規(guī)范咐扭,所以這就是bable存在的意義滑废。
url-loader:對資源文件做base64編碼蠕趁,它有個(gè)參數(shù)limit辛馆,比如一張圖片小于這個(gè)limit的值昙篙,那url-loader會(huì)幫你轉(zhuǎn)成base64編碼嵌入引用這張圖片的qit模塊中,這樣瀏覽器就不需要多一個(gè)網(wǎng)絡(luò)請求缴挖,去請求圖片焚辅,增加網(wǎng)頁的響應(yīng)時(shí)間法焰。當(dāng)然超過這個(gè)值的話,還是給你提供成url鏈接乙濒。工程中的配置颁股,可以看到它對圖片傻丝,視頻,字體文件都可以轉(zhuǎn)亏掀。
vue-loader:vue官方提供的對vue文件的處理滤愕,它會(huì)將vue文件中css的部分交由webpack指定的css-loader處理怜校,js和模板交由webpack的js指定loader也就是babel-loader處理;處理具體配置不多講茄茁,參考https://github.com/vuejs/vue-loader
~~~~~~~~~~~~~~分割線~~~~~~~~~~~~~~~~~~~
現(xiàn)在我們知道了巩割,webpack.base.conf.js配置了基礎(chǔ)性的配置宣谈,然后我們的配置暴露出去机蔗。那我們怎么使用它呢萝嘁?首先我們知道package.json幫我們配置了build 和 dev 兩個(gè)任務(wù),它們分別對應(yīng)執(zhí)行的 npm run lint && node build/build.js 和 node build/dev-server.js酸钦。npm run build, 先執(zhí)行eslint卑硫,幫忙lint一下代碼的風(fēng)格蚕断,然后執(zhí)行node build/build.js 亿乳。那我們先看build.js
require('./check-versions')()
process.env.NODE_ENV = 'production'
var ora = require('ora') // 一個(gè)用于在命令窗口提示類似程序處理中,loading中之類文字障陶,以起到提醒標(biāo)注作用
var rm = require('rimraf') // rm 刪除目錄抱究,清空目錄的工具包
var path = require('path')
var chalk = require('chalk') // 在命令窗口輸出有顏色的文字工具包
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...') // 命令窗口會(huì)出現(xiàn)一個(gè)loading轉(zhuǎn)圈
spinner.start()
// rm 幫我們每次構(gòu)建前带斑,清理一下之前構(gòu)建好的舊文件勋磕,清理完后執(zhí)行回調(diào)函數(shù)
// 回調(diào)函數(shù)里執(zhí)行webpack打包
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) { //webpack打包后執(zhí)行回調(diào)函數(shù),向控制臺輸出自己構(gòu)建結(jié)果信息
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'
))
})
})
webapck有兩種使用方式:
第一種: 命令行里webpack --config src/main.js
第二種: 就是require('webpack')醋安, 給webpack傳入config配置對象墓毒,然后執(zhí)行這段node腳本所计,即node build/build.js
然后我們就可以知道团秽,webpack配置參數(shù)config是從webpack.prod.conf引入的:
webpack.prod.conf.js: 這里主要是用了webpack-merge 合并基礎(chǔ)的配置习勤,根據(jù)環(huán)境的不同,添加不同的配置夷都。prod就是prodution生產(chǎn)環(huán)境囤官。這里面用到了一些插件蛤虐,具體我都注釋到上面
var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
var env = config.build.env
// 利用webpack-merge 合并我們的baseWebpackConfig配置驳庭。 webpack-merge能夠讓你動(dòng)態(tài)改變webpack配置
var webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true
})
},
devtool: config.build.productionSourceMap ? '#source-map' : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
// 添加chunkhash值嚷掠,指每次構(gòu)建的值都不一樣,業(yè)務(wù)代碼經(jīng)常變化贯城,添加chunkhash避免瀏覽器緩存使用舊代碼
// chunkhash與hash區(qū)別在于:前者是每次構(gòu)建都不一樣能犯,后者是只要你的文件名是一樣的犬耻,是不會(huì)變化的枕磁,一般用chunkhash多一些
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
// DefinePlugin用于在webpack構(gòu)建中,定義參數(shù)茸苇,然后你可以在webpack構(gòu)建配置中引用這個(gè)參數(shù)做一些配置上的判斷学密,賦值
new webpack.DefinePlugin({
'process.env': env
}),
// js壓縮插件,用于代碼壓縮彤守,然后去掉注釋哭靖,生成soucemap便于調(diào)試定位問題
// 構(gòu)建生產(chǎn)環(huán)境生成sourcemap比較耗時(shí)款青,一般你也可以不用抡草,在開發(fā)環(huán)境才生成sourcemap
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
// extract css into its own file
// 正如上面的英文注釋一樣,這個(gè)插件主要是將css內(nèi)容獨(dú)立抽出來燎含,而不是變成一個(gè)js模塊綁如bundle中
// 官網(wǎng)說:這樣能夠加快整體構(gòu)建速度屏箍,同時(shí)有利于js和css分開
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css')
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
// 用于壓縮css的插件
new OptimizeCSSPlugin({
cssProcessorOptions: {
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
// 這個(gè)是老朋友了赴魁,將我們的bundle注入到index.html,同時(shí)對html進(jìn)行壓縮處理钝诚,
// 這里要注意一下:
// 1.minify壓縮配置
// 2.chunkSortMode:這個(gè)參數(shù)一般選擇dependency凝颇,因?yàn)槟憧梢园阉心K打包成一個(gè)文件,但是這樣效率最低芦岂,一般我們會(huì)抽出
// 公共模塊禽最,產(chǎn)生多個(gè)bundle,引入bundle的順序就由這插件來引入瓢喉;選擇 dependency,意思就是誰先被依賴决左,誰先被引入
// 3.inject: 有三種方式 true/'head'/'body',其實(shí)就是指指定你要把這些bundle在什么地方引入佛猛,跟你引入js文件的script標(biāo)簽放在哪里是一個(gè)意思
new HtmlWebpackPlugin({
filename: 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'
}),
// split vendor js into its own file
// 這個(gè)是指定一個(gè)公共模塊插件继找,這個(gè)插件用于定義哪些可以算是公共模塊
// 構(gòu)建過程中,這插件會(huì)根據(jù)我們minChunks的配置判斷哪些是公共模塊幻锁,抽取出來合一個(gè)name為ventor的bundle
// 我們可以看出:只要是從node_modules中出來的判定為公共模塊
// 另外name為什么不是'vendor[chunkhash:7]',name不加hash值是充分利用瀏覽器的緩存哄尔,因?yàn)槲覀児材K一般不會(huì)變化(除非技術(shù)棧升級),瀏覽器端有了緩存就不用重復(fù)請求
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// 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',
chunks: ['vendor']
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
var 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) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
到這里就很清晰了:
webpack的配置思維:
var webpack = require('webpack')
var merge = require('webpack-merge')
webpack(merge(baseconfig,diffent_config)) // diffent_config指根據(jù)開發(fā)環(huán)境或生產(chǎn)環(huán)境做不同的配置
~~~~~~~~~~~~~~分割線~~~~~~~~~~~~~~~~~~~
現(xiàn)在我們來看看開發(fā)環(huán)境怎么配置鸣戴,一般我們會(huì)喜歡每個(gè)以模塊改動(dòng)后粘拾,能夠自動(dòng)更新半哟,同時(shí)不需要刷新瀏覽器就能看到修改。帶著疑問盯串,我們看看工程里是如何配置的体捏。
npm run dev 對應(yīng)著 node build/dev-server.js(package.json寫,別忘了哈)
我們看看dev-server.js
require('./check-versions')() // 就是對應(yīng)check-version.js 檢查你當(dāng)前 node和npm 的版本看看是否符合要求
var config = require('../config')
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn')
var path = require('path')
var express = require('express') //express,一個(gè)node的web框架
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')
// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port // 這里其實(shí)也是使用config配置的dev.port;
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser // 服務(wù)啟動(dòng)成功后是否自動(dòng)打開瀏覽器,看config里面配置了true or false
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable //
var app = express() // 新建node http server 年栓,大家可以學(xué)一下express框架某抓,很簡單卻很強(qiáng)大
var compiler = webpack(webpackConfig)
// webpack-dev-middleware插件是將webpack返回的compiler傳給node server服務(wù)
// 這個(gè)插件的一個(gè)好處是:webpack構(gòu)建的bundle都是存在內(nèi)存中否副,而不是向硬盤輸出
// 配合webpack-hot-midlleware使用备禀,達(dá)到熱更新的目的
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
})
// 這個(gè)就是我們的熱更新了,當(dāng)你改動(dòng)一個(gè)模塊(比如test.vue),改完按保存時(shí)赋续,這個(gè)插件會(huì)通知compile重新對這個(gè)模塊更新打包
// compile更新后,又會(huì)由devMiddleware插件將構(gòu)建的內(nèi)容傳給node server 服務(wù)队腐,并通知瀏覽器更新蚕捉,達(dá)到我們不需要手動(dòng)刷新瀏覽器就能看到我們的改動(dòng)的內(nèi)容
// heartbeat 心跳機(jī)制,每隔2秒檢查模塊是否發(fā)生變化(它怎么檢查柴淘,是一件有技術(shù)的事情迫淹,通過對比chunk的id,具體怎么實(shí)現(xiàn)要看源碼了)
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: false,
heartbeat: 2000
})
// force page reload when html-webpack-plugin template changes
// 編譯器處理的一個(gè)編譯完成的鉤子函數(shù)
// 完成是調(diào)用为严,其實(shí)就是編譯完成通知hotMiddleware 發(fā)布reload action給瀏覽器
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
// 在config中有個(gè)配置代理的敛熬,很多情況下第股,我們開發(fā)在本地应民,請求數(shù)據(jù)的接口在其他域名下,這個(gè)時(shí)候我們需要配置代理
// 這種配置其實(shí)個(gè)人覺得沒有那么方便夕吻,因?yàn)槟阃晖耆梢灾苯觓pp.use代理一個(gè)請求诲锹,代碼更加直觀些
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// serve pure static assets
// express 托管靜態(tài)資源
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
var uri = 'http://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
console.log('> Starting dev server...')
// devMiddleware 監(jiān)聽編譯器編譯完成后執(zhí)行回調(diào)函數(shù)
// 這里判斷了config是否設(shè)置了自動(dòng)打開瀏覽器
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) // 啟動(dòng)服務(wù)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}
dev環(huán)境思想就是:利用devmiddle 中間件,講webpack的編譯器傳給node server 服務(wù)涉馅,并搭配hotmiddle 心跳監(jiān)測模塊是否更改归园,當(dāng)更改后,編譯完成稚矿,由hotmiddle發(fā)布一個(gè)reload的action庸诱,然后瀏覽器更新顯示捻浦。
而webpack的配置則是引用webpack.dev.conf.js
webpack.dev.conf.js: 同樣也是引入基礎(chǔ)配置,然后merge合并一下桥爽。有個(gè)注意點(diǎn)朱灿,它修改了entry,里面entry本來只是main.js钠四,現(xiàn)在變成兩個(gè)盗扒,build/dev-client.js 和main.js。dev-client注入個(gè)事件回調(diào)缀去,當(dāng)event.action = 'reload',是window.local.reload() 這個(gè)時(shí)候你就明白环疼,hotmiddle發(fā)布了reload的action,瀏覽器為什么會(huì)更新
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf') // 同樣的是引入基礎(chǔ)配置
var HtmlWebpackPlugin = require('html-webpack-plugin')
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') // 增加友好報(bào)錯(cuò)插件朵耕,讓我們開發(fā)中,能夠更好了解報(bào)錯(cuò)信息
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})
module.exports = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
},
// cheap-module-eval-source-map is faster for development
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new FriendlyErrorsPlugin()
]
})
最后有個(gè)小問題:css的處理的loader到哪里去了淋叶?
其實(shí)因?yàn)関ue支持less 阎曹、sass、stylus 三種預(yù)編譯css語言煞檩,所以在工程里給我們封裝了一個(gè)util.js处嫌,里面有個(gè)styleloader的方法,主要是根據(jù)你的vue組件里面<style>標(biāo)簽的lang屬性斟湃,動(dòng)態(tài)增加對應(yīng)loader處理熏迹。大家可以看看里面是什么,挺有趣的凝赛。
系列文章:
《什么是構(gòu)建注暗? webpack打包思想?》
《webpack基礎(chǔ)使用》
《從vue-cli學(xué)webpack配置1——針對webpack2》
《從vue-cli學(xué)webpack配置2——針對webpack3》
《webpack 墓猎、mainfest 捆昏、runtime 、緩存與CommonsChunkPlugin》
《webpack打包慢的解決方案》