本文為翻譯文章懈费,對文章內(nèi)容進(jìn)行部分舍去耍鬓,原文地址Webpack-the confusing parts唯沮。
一.Webpack的核心哲學(xué)
webpack有2個(gè)核心概念:
- 一切皆模塊埋虹,就像JS文件能當(dāng)作模塊一樣盼玄,其余文件(CSS, IMAGES, HTML)也能當(dāng)作模塊。即缘薛,你能夠require("myJsFile.js") 或 require("myCSSFile.css"),這意味著我們可以任意“手工制品”拆分成任意更小的可控制的塊窍育,從而使之可重用;
- 只加載你想要的和你什么時(shí)候需要的, 一般模塊打包將所有的模塊生成一個(gè)大的單一的"bundle.js"文件宴胧。但是在現(xiàn)實(shí)中漱抓,這個(gè)"bundle.js"文件可能會(huì)10MB-15MB,這樣加載會(huì)很慢恕齐! 因此webpack擁有豐富的功能來拆分代碼乞娄, 產(chǎn)生多個(gè)"bundle"文件, 同時(shí)實(shí)現(xiàn)異步的加載檐迟,這就是 load what you need and when you need it.
二.開發(fā)和產(chǎn)品
首先應(yīng)該意識到的是webpack擁有豐富的功能补胚,一些只能用于開發(fā)(Development-only), 一些只用于產(chǎn)品(Production-only), 一些兩者都可以(Production-and-Development)。
// Development-only 列舉部分只用于開發(fā)的配置
module.exports = {
// ...
devtoolo: "source-map",
devServer: {
colors: true,
historyApiFallback: true,
inline: true,
hot: true,
contentBase: "./public"
},
plugins: [
new HotModuleReplacementPlugin(),
// ...
],
}
// Production-only 只用于產(chǎn)品
{
plugins: [
// ...
new AppCachePlugin({ // 產(chǎn)生"manifest.appcache"
excluede: ["htaccess"]
}),
new webpack.optimize.UglifyJsPlugin() // 壓縮代碼
]
}
// Production-and-Development
{
output: {
publicPath: "/" // 開發(fā)時(shí)用
}
}
{
output: {
publicPath: "http://someCDN.com/" // 產(chǎn)品時(shí)用追迟,這個(gè)值產(chǎn)品和開發(fā)時(shí)不一樣
}
}
因此產(chǎn)品一般有2個(gè)webpack配置文件: webpack.config.js, webpack.config.production.js
在package.json中配置
"script": {
// "npm run build": 生成產(chǎn)品打包的文件
"build": "webpack --config webpack.config.production.js -p",
// "npm run dev": 生成開發(fā)打包的文件
"dev": "webpack-dev-server --colors --hot --inline"
}
二. webpack CLI 和 webpack-dev-server
webpack提供了2個(gè)接口:
- Webpack CLI tool溶其, 默認(rèn)接口(作為webpack的部分安裝)
- webpack-dev-server tool, 一個(gè)Node.js server(單獨(dú)安裝的)
1.Webpack CLI(Good for Production Builds)
使用方法:
// 選項(xiàng)1: 全局安裝, 在Termnal中使用
npm install webpack -g
$ webpack // 產(chǎn)生打包文件
// 選項(xiàng)2: 本地安裝敦间,添加到package.json中
npm install webpack --save
// "package.json"
"scripts": {
"build": "webpack --config webpack.config.production.js -p"
}
// 使用方法
$ npm run build
2.Webpack-dev-server(Good for Development Builds)
這是一個(gè)Exprss node.js server瓶逃, 默認(rèn)端口為8080,這個(gè)server內(nèi)部調(diào)用Webpack廓块。好處就是提供實(shí)時(shí)刷新(live Reloading) 和 只替代變化的模塊, 比如Hot Module Replacement(HMR)
使用方法:
// 選項(xiàng)1: 全局安裝, 終端使用
npm install -g webpack-dev-server
$ webpack-dev-server --inline --hot
// 選項(xiàng)2: 添加到"package.json"中
"scripts": {
"start": "webpack-dev-server --inline --hot"
}
$ npm start
--inline: 表示實(shí)時(shí)刷新厢绝,一般將整個(gè)頁面進(jìn)行刷新
--hot: 表示熱取代, 只替換變化的部分
一般這2個(gè)標(biāo)簽一起使用带猴,在webpack.config.js中配置
{
devServer: {
inline: true,
hot: true
}
}
三."entry" --- 字符串昔汉, 數(shù)組, 對象###
配置文件中"entry"有3種表達(dá)形式拴清,字符串靶病,數(shù)組或?qū)ο螅?不同的類型有不同的目的群井,如果時(shí)單一的starting point湿刽,任何形式功能一樣:
entry: "./public/src/index.js"
entry: ["./public/src/index.js"]
entry: { index: "./public/src/index.js" }
1.entry - Array形式
如果要添加多個(gè)相互之間獨(dú)立的文件,可以使用數(shù)組的形式, 比如在HTML中需要"googleAnalytics.js"
{
entry: ["./public/src/index.js", "./public/src/googleAnalytics.js"],
output: {
path: "./dist",
filename: "bundle.js"
}
}
2.entry - 對象形式
如果有多頁面應(yīng)用羹奉,不是SPA沪停,比如多個(gè)HTML文件(index.html和profile.html),可以使用webpack通過 entry object 一次性生成多個(gè)打包文件
{
entry: {
"indexEntry": "./public/src/index.js",
"profileEntry": "./public/src/profile.js"
},
output: {
path: "./dist",
filename: "[name].js" // indxeEntry.js & profileEntry.js
}
}
3.entry - combination
可以在對象entry中使用數(shù)組:
// 產(chǎn)生3個(gè)文件
{
entry: {
"vendor": ["jQuery", "analytics.js", "optimizely.js"],
"index": "./public/src/index.js",
"profile": "./public/src/profile.js"
},
output: {
path: "./dist",
filename: "[name].js" // vendor.js & indxe.js & profile.js
}
}
四.output- "path" Vs "publicPath"
output告訴webpack在哪里存放產(chǎn)生的文件煤辨,有2個(gè)屬性"path"和"publicPath":
- path: 僅告訴webpack在哪里存放結(jié)果
- publicPath: 使用插件用于更新CSS中的 URLs, HTML文件裳涛,比如,在開發(fā)時(shí)众辨,css文件中圖片使用本地圖片"./test.png",在產(chǎn)品階段端三, "test.png"可能存放在某個(gè)CDN上,可以手動(dòng)更新這個(gè)URL泻轰, 也可以使用Webpack的publicPath和一些插件在產(chǎn)品階段的自動(dòng)更新這些URLs
.image {
background-image: url("./test.png")
}
// 產(chǎn)品階段
.image {
background-image: url("https://someCDN/test.png")
}
五.鏈?zhǔn)郊虞d器
多個(gè)Loaders能夠鏈?zhǔn)降膶ο嗤募愋瓦M(jìn)行操作技肩,the chaining works from right-to-left and the loader are separated by
// npm install --save-dev style-loader css-loader sass-loader autoprefixer-loader
module: {
loaders: [
{
test: /\.scss$/,
loader: "style!css?modules&importLoaders=2&sourceMap&localIdentName=[local]__[hash:base64:5]!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap"
}
]
}
六.Loaders自身可配置
Loaders自身也有參數(shù),也可以進(jìn)行配置浮声,比如 url-loader
// 使用"?"就像URLs
{
test: /\.(png|jpg)$/,
loader: "url-loader?limit=1024"
}
// 也可以使用"query"屬性
{
test: /\.(png|jpg)$/,
loader: "url-loader",
query: {
limit: 1024
}
}
上面的 "1024" 表示圖標(biāo)超過1024bytes就使用base64編碼格式
七. ".babelrc" 文件###
babel-loader 使用 presets
配置轉(zhuǎn)換ES6->ES5, JSX->JS, 可以通過 query
參數(shù)
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: "babel",
query: {
presets: ["react","es2015"]
}
}
]
}
在很多的項(xiàng)目中babel的配置會(huì)非常的大, 可以單獨(dú)的放在 .babelrc
文件中旋奢, babel-loader會(huì)自動(dòng)的加載 .babelrc 文件中的配置信息
// webpack.config.js
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: "babel"
}
]
}
// .babelrc
{
"presets": ["react", "es2015"]
}
八.插件
插件是額外的node模塊泳挥,通常對打包好的bundle進(jìn)行處理。 例如: UglifyJsPlugin
對bundle.js進(jìn)行壓縮處理至朗; extract-text-webpack-plugin
內(nèi)部使用 css-loader 和 style-loader將所用CSS集中到一個(gè)地方屉符,最后提取結(jié)果,生成一個(gè) style.css 外部文件锹引。
// Take all the .css files, combine their contents and
// it extract them to a single "style.css"
var ETP = require("extract-text-webpack-plugin");
module: {
loaders: [
{ test: /\.css$/, loader: ETP.extract("style-loader", "css-loadeer") }
]
},
plugins: [
new ExtractTextPlugin("style.css") // 提取到 style.css 文件
]
如果向?qū)?內(nèi)聯(lián)css(inline css) 作為一個(gè)style元素加入到HTML中矗钟, 可以不適用 extract-text-webpack-plugin,而只使用css-loader, style-loader
module: {
loaders: [
{ test: /\.css$/, loader: "style!css" }
]
}
九.插件和Loaders的區(qū)別
Loaders work at the individual file level during or before the bundle is generated.(加載器在bundle產(chǎn)生前或產(chǎn)生過程中對單獨(dú)的文件進(jìn)行處理)
Plugins work at bundle or chunk level and usually work at the end of the bundle generation process(插件在bundle生成之后對bundle 或 塊級別進(jìn)行處理), 有一些插件嫌变,比如 commonsChunksPlugins 對bundles的創(chuàng)建進(jìn)一步的進(jìn)行修改
十.Resolving File Extensions
許多webpack 配置文件有一個(gè) resolve extensions 屬性吨艇,擁有一個(gè) empty string。 empty string時(shí)幫助解決 imports文件中沒有擴(kuò)展的文件的腾啥, 比如 require("./myJsFile") 或 import myJsFile from "./myJsFile"
{
resolveL: {
extensions: ["", ".js", ".jsx"]
}
}