翻譯 | webpack2的入門(mén)手冊(cè)

背景

一直對(duì)webpack的打包流程很感興趣,但是無(wú)奈官網(wǎng)文檔實(shí)在太多,搜出來(lái)的大部分文章要么偏理論要么純粹講過(guò)程不講原理,最近終于找到一篇入門(mén)文章,文章對(duì)于初學(xué)者講的很清晰,但是由于是英文的,而且我沒(méi)有找到這篇文章對(duì)應(yīng)的中文翻譯版,所以本文主要是對(duì)那篇文章進(jìn)行翻譯,介紹一下webpack2的入門(mén)知識(shí)。
注:本人翻譯水平有限,如果有錯(cuò)誤,歡迎指正。
原文地址:A Beginner’s Guide to Webpack 2 and Module Bundling
原文作者:Mark Brown
譯文作者:Allen Gong

webpack2入門(mén)手冊(cè)(譯文)

Webpack是一個(gè)模塊打包機(jī)

Webpack已然成為當(dāng)前web開(kāi)發(fā)最重要的工具之一。首先它是一個(gè)Javascript的打包工具,但同時(shí)他也能打包包括HTML,CSS,甚至是圖片等形式的資源。它能更好的控制你正在編寫(xiě)的App的HTTP請(qǐng)求,并且允許你去使用更多的資源(如Jade,Sass以及ES6)。Webpack同時(shí)允許你更容易的從npm獲取安裝包。

這篇文章主要面向那些對(duì)于webpack完全陌生的同學(xué),內(nèi)容將包括初始安裝和配置,模塊,模塊加載器,插件,代碼拆分以及模塊熱替換(HMR,hot module replacement)。如果你覺(jué)得入門(mén)視頻比較有用的話,我推薦Glen Maddern的Webpack初體驗(yàn)作為開(kāi)始學(xué)習(xí)的起點(diǎn),會(huì)讓你理解為什么webpack如此特殊。

為了更加后續(xù)的閱讀,請(qǐng)確保先安裝了Node.js,安裝可以參考Node.js安裝教程。你也在Github上下載到對(duì)應(yīng)的Demo

安裝

讓我們用npm和webpack新建一個(gè)項(xiàng)目吧:

mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack@beta --save-dev
mkdir src
touch index.html src/app.js webpack.config.js

編輯以下文件:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello webpack</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="dist/bundle.js"></script>
  </body>
</html>
// src/app.js
const root = document.querySelector('#root')
root.innerHTML = `<p>Hello webpack.</p>`
// webpack.config.js
const webpack = require('webpack')
const path = require('path')

const config = {
  context: path.resolve(__dirname, 'src'),
  entry: './app.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{
      test: /\.js$/,
      include: path.resolve(__dirname, 'src'),
      use: [{
        loader: 'babel-loader',
        options: {
          presets: [
            ['es2015', { modules: false }]
          ]
        }
      }]
    }]
  }
}

module.exports = config

以上的設(shè)置只是通用配置,它會(huì)指導(dǎo)你的webpack將我們的入口文件src/app.js編譯輸入為/dist/bundle.js,并且所有的.js文件都將通過(guò)Babel從ES2015轉(zhuǎn)換為ES5。

為了讓這個(gè)項(xiàng)目能運(yùn)行起來(lái),我們需要安裝三個(gè)安裝包,babel-core,webpack的加載器babel-loader以及預(yù)處理模塊babel-preset-es2015,這些模塊都是為了支持Javascript的編寫(xiě)。{ modules: false }可以確保使用Tree Shaking去去除掉不必要的模塊,同時(shí)會(huì)降低文件大小。

npm install babel-core babel-loader babel-preset-es2015 --save-dev

最后使用下面代碼更新package.json:

"scripts": {
  "start": "webpack --watch",
  "build": "webpack -p"
},

運(yùn)行npm start將會(huì)以觀察模式啟動(dòng)webpack,在這種模式下,會(huì)持續(xù)監(jiān)聽(tīng)我們src文件夾下的.js文件??刂婆_(tái)的輸出結(jié)果顯示了生成的打包后的文件,我們應(yīng)該持續(xù)關(guān)注生成的文件的大小和數(shù)量。

現(xiàn)在你可以在瀏覽器中訪問(wèn)index.html,將會(huì)看到“Hello webpack.”

open index.html

打開(kāi)dist/bundle.js看看webpack到底做了什么事,在文件的頂部是bootstrapping模塊的代碼,在它下面是我們自己的模塊。你可能目前還沒(méi)有什么感覺(jué)webpack好處,但是你現(xiàn)在可以編寫(xiě)ES6代碼并且webpack將會(huì)把各個(gè)模塊打成生產(chǎn)所需要的包,這樣所有瀏覽器都能訪問(wèn)。

使用Ctrl + C停止webpack的服務(wù),運(yùn)行npm run build,編譯成生成環(huán)境所需要的包。

注意:包的大小從2.61 kB降到了585 bytes
重新看看dist/bundle.js,你會(huì)發(fā)現(xiàn)代碼變得一團(tuán)糟,UglifyJS對(duì)打包后的代碼進(jìn)行了壓縮,運(yùn)行起來(lái)是沒(méi)有差別的,但同時(shí)字符數(shù)是相當(dāng)少的。

模塊

對(duì)于外部模塊,webpack有多種方式去引入,其中比較重要的兩種是:

  • ES2015的import方法
  • CommonJS的require()方法

我們可以通過(guò)安裝lodash來(lái)測(cè)試上述方式,并且導(dǎo)入到app.js中。

npm install lodash --save
// src/app.js
import {groupBy} from 'lodash/collection'

const people = [{
  manager: 'Jen',
  name: 'Bob'
}, {
  manager: 'Jen',
  name: 'Sue'
}, {
  manager: 'Bob',
  name: 'Shirley'
}, {
  manager: 'Bob',
  name: 'Terrence'
}]
const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`

運(yùn)行npm start重啟webpack并刷新index.html,你會(huì)在頁(yè)面上看到一個(gè)按照manager分好組人名的數(shù)組。
接下來(lái)讓我們把這個(gè)數(shù)組部分單獨(dú)放在people.js這個(gè)模塊里。

// src/people.js
const people = [{
  manager: 'Jen',
  name: 'Bob'
}, {
  manager: 'Jen',
  name: 'Sue'
}, {
  manager: 'Bob',
  name: 'Shirley'
}, {
  manager: 'Bob',
  name: 'Terrence'
}]

export default people

我們可以以相對(duì)路徑的方式將模塊導(dǎo)入到app.js

// src/app.js
import {groupBy} from 'lodash/collection'
import people from './people'

const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`

注意:導(dǎo)入像'lodash/collection這種不使用相對(duì)路徑的,是那些通過(guò)npm安裝的,從/node_modules中引入,你自定義的模塊則需要像'./people'相對(duì)路徑的方式引入,通過(guò)這種方式可以對(duì)兩種模塊進(jìn)行區(qū)分。

加載器

我們已經(jīng)介紹了babel-loader,它是眾多loader中的一種,能夠告訴webpack當(dāng)遇到不同的文件時(shí)如何處理。比較好的方式是將loader進(jìn)行串聯(lián),加載到一個(gè)加載器中,我們通過(guò)從Javascript中引入Sass包來(lái)看看loader是如何進(jìn)行工作的。

Sass

這個(gè)轉(zhuǎn)換器包括了三個(gè)單獨(dú)的加載器和node-sass庫(kù):

npm install css-loader style-loader sass-loader node-sass --save-dev

在配置文件中為.scss引入新的規(guī)則:

// webpack.config.js
rules: [{
  test: /\.scss$/,
  use: [
    'style-loader',
    'css-loader',
    'sass-loader'
  ]
}, {
  // ...
}]

注意:不管什么時(shí)候你改變了webpack.config.js中的加載規(guī)則,你都需要通過(guò)Ctrl + C然后npm start的方式重啟webpack。

loader以倒序的方式運(yùn)行:

  • sass-loader轉(zhuǎn)換Sass成CSS
  • css-loader將CSS解析Javascript并解決依賴包問(wèn)題
  • style-loader將CSS導(dǎo)出成<tag>便簽放在document下

你可以將上述過(guò)程想象成函數(shù)的調(diào)用關(guān)系,一個(gè)函數(shù)運(yùn)行的結(jié)果作為另一個(gè)函數(shù)的輸入:

styleLoader(cssLoader(sassLoader('source')))

接下來(lái)讓我們?cè)黾右粋€(gè)Sass源文件:

/* src/style.scss */
$bluegrey: #2B3A42;

pre {
  padding: 20px;
  background: $bluegrey;
  color: #dedede;
  text-shadow: 0 1px 1px rgba(#000, .5);
}

現(xiàn)在你可以在你的app.js中直接引入Sass文件:

// src/app.js
import './style.scss'

// ...

刷新index.html你會(huì)看到樣式發(fā)生了變化。

Javascript中的CSS

我們剛剛把Sass作為一個(gè)模塊引入到我們的入口文件中。

打開(kāi)dist/bundle.js,搜索pre {。事實(shí)上,Sass已經(jīng)被編譯成一段CSS的字符串,并以模塊的形式存在。當(dāng)我們?cè)谖覀兊腏avascript文件中導(dǎo)入這個(gè)模塊時(shí),style-loader就會(huì)將其編譯輸出成內(nèi)嵌的<style>標(biāo)簽。

我知道你在想什么?為什么要這么做?

關(guān)于這個(gè)問(wèn)題,我在這個(gè)話題中不想說(shuō)太多,但下面幾個(gè)原因值得思考一下:

  • 如果你想在項(xiàng)目中引入一個(gè)Javascript組件并正常運(yùn)行,可能需要依賴很多其他資源(如HTML, CSS, Images, SVG),如果我們將所有資源打包到一起,將會(huì)非常易于引入和使用。
  • 去除寫(xiě)死的代碼:當(dāng)一個(gè)JS組件不再被代碼引入到項(xiàng)目中,對(duì)應(yīng)的CSS也不會(huì)被引入進(jìn)來(lái)。而最終打包后的結(jié)果也只會(huì)包含那些被引用的部分。
  • CSS模塊:由于全局CSS命名空間的存在,使得改變CSS后是否有副作用不得而知。CSS模塊默認(rèn)情況下將CSS設(shè)成本地,并顯示你在Javascript中可以引用的唯一類名。
  • 通過(guò)捆綁/分割代碼的巧妙方式減少HTTP請(qǐng)求的數(shù)量。

圖片

最后一個(gè)關(guān)于loader的例子是關(guān)于處理圖片的url-loader。
在標(biāo)準(zhǔn)HTML文檔中,圖片通過(guò)<img>標(biāo)簽或者background-image屬性獲得。但是通過(guò)webpack,一些小圖片可以以字符串的形式存儲(chǔ)在Javascript中。通過(guò)這種方式,你可以在預(yù)加載的時(shí)候就獲取到圖片,從而不需要單獨(dú)的請(qǐng)求去請(qǐng)求圖片。

npm install file-loader url-loader --save-dev

在配置文件中增加一條圖片的規(guī)則:

// webpack.config.js
rules: [{
  test: /\.(png|jpg)$/,
  use: [{
    loader: 'url-loader',
    options: { limit: 10000 } // Convert images < 10k to base64 strings
  }]
}, {
  // ...
}]

通過(guò)Ctrl + Cnpm start重啟服務(wù)。
通過(guò)下面的命令下載一個(gè)測(cè)試圖片:

curl https://raw.githubusercontent.com/sitepoint-editors/webpack-demo/master/src/code.png --output src/code.png

現(xiàn)在可以在app.js中加載圖片資源:

// src/app.js
import codeURL from './code.png'
const img = document.createElement('img')
img.src = codeURL
img.style.backgroundColor = "#2B3A42"
img.style.padding = "20px"
img.width = 32
document.body.appendChild(img)

// ...

這樣頁(yè)面中多了一個(gè)img,它的src屬性包含了圖片自身的data URI。

<img src="data:image/png;base64,iVBO..." style="background: #2B3A42; padding: 20px" width="32">

同時(shí),因?yàn)?code>css-loader的緣故,通過(guò)url()屬性引入的圖片,也通過(guò)url-loader轉(zhuǎn)換成行內(nèi)元素。

/* src/style.scss */
pre {
  background: $bluegrey url('code.png') no-repeat center center / 32px 32px;
}

編譯后變成:

pre {
    background: #2b3a42 url("data:image/png;base64,iVBO...") no-repeat scroll center center / 32px 32px;
}

模塊到靜態(tài)資源

現(xiàn)在你可以webpack是如何幫助你對(duì)將你項(xiàng)目中一系列的依賴資源進(jìn)行打包處理的,下面這張圖是webpack官網(wǎng)主頁(yè)上的。

雖然Javascript是入口文件,但是webpack還是傾向于你的其他類型的資源像HTML, CSS, and SVG能有自己的依賴,把它們作為構(gòu)建包的一部分。

插件

我們已經(jīng)看過(guò)了webpack其中一個(gè)構(gòu)建插件的例子,使用UglifyJsPluginnpm run build腳本可以調(diào)用webpack -p,它的作用是與webpack搭配壓縮生成后的包。
當(dāng)loader在單個(gè)文件上操作相應(yīng)變換時(shí),插件可以在各個(gè)大型代碼塊上交叉運(yùn)行。

公共代碼

commons-chunk-plugin是另一個(gè)核心插件,搭配webpack用來(lái)創(chuàng)建在多個(gè)入口文件中使用的擁有公共代碼的單文件模塊。到目前為止,我們使用的都是單一入口和單一出口文件。但是很多real-world scenarios中更好的方法是使用多文件入口和多文件出口。
如果你在你的應(yīng)用中有兩個(gè)完全獨(dú)立的領(lǐng)域但是卻擁有共同的模塊,舉個(gè)例子,app.js是面向用戶的,admin.js是面向管理員的,你就可以為他們單獨(dú)創(chuàng)建不同的入口文件,就像下面這樣:

// webpack.config.js
const webpack = require('webpack')
const path = require('path')

const extractCommons = new webpack.optimize.CommonsChunkPlugin({
  name: 'commons',
  filename: 'commons.js'
})

const config = {
  context: path.resolve(__dirname, 'src'),
  entry: {
    app: './app.js',
    admin: './admin.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  module: {
    // ...
  },
  plugins: [
    extractCommons
  ]
}

module.exports = config

注意對(duì)于結(jié)果文件,現(xiàn)在包含了名字,這樣我們區(qū)分出兩個(gè)不同的結(jié)果文件對(duì)應(yīng)不同的入口文件:app.bundle.jsadmin.bundle.js。

commonschunk插件生成了第三個(gè)文件commons.js,他包含了我們?nèi)肟谖募墓材K。

// src/app.js
import './style.scss'
import {groupBy} from 'lodash/collection'
import people from './people'

const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`
// src/admin.js
import people from './people'

const root = document.querySelector('#root')
root.innerHTML = `<p>There are ${people.length} people.</p>`

這些入口文件將會(huì)產(chǎn)生下列文件:

  • app.bundle.js:包括樣式和lodash/collection模塊
  • admin.bundle.js:不包含任何額外模塊
  • commons.js:包含了我們公共的people模塊

我們可以在兩個(gè)入口文件中都引入公共模塊:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello webpack</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="dist/commons.js"></script>
    <script src="dist/app.bundle.js"></script>
  </body>
</html>
<!-- admin.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello webpack</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="dist/commons.js"></script>
    <script src="dist/admin.bundle.js"></script>
  </body>
</html>

試試在瀏覽器中重新加載index.htmladmin.html,看看自動(dòng)生成的公共模塊部分。

抽取CSS

另一個(gè)受歡迎的插件是extract-text-webpack-plugin,它的用途是抽取模塊到對(duì)應(yīng)的結(jié)果文件中。
下面我們?cè)谂渲梦募行薷?code>.scss的規(guī)則編譯成對(duì)應(yīng)的Sass文件,加載CSS,接著把他們抽取到各自的CSS包中,這樣就可以把它們從Javascript包中移除。

npm install extract-text-webpack-plugin@2.0.0-beta.4 --save-dev
// webpack.config.js
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const extractCSS = new ExtractTextPlugin('[name].bundle.css')

const config = {
  // ...
  module: {
    rules: [{
      test: /\.scss$/,
      loader: extractCSS.extract(['css-loader','sass-loader'])
    }, {
      // ...
    }]
  },
  plugins: [
    extractCSS,
    // ...
  ]
}

重啟webpack你會(huì)看到一個(gè)新的打包后的文件app.bundle.css,你可以照例直接引用它。

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello webpack</title>
    <link rel="stylesheet" href="dist/app.bundle.css">
  </head>
  <body>
    <div id="root"></div>
    <script src="dist/commons.js"></script>
    <script src="dist/app.bundle.js"></script>
  </body>
</html>

刷新頁(yè)面,確認(rèn)CSS已經(jīng)被編譯過(guò)了,并從app.bundle.js移到了app.bundle.css,成功了!

代碼拆分

我們已經(jīng)看了幾種代碼拆分的方法:

  • 手動(dòng)創(chuàng)建單獨(dú)的入口文件
  • 自動(dòng)將公共代碼拆分到公共模塊中
  • 使用extract-text-webpack-plugin從編譯后的代碼中抽取出來(lái)

拆分包還有其他方法:System.importrequire.ensure。通過(guò)在這些函數(shù)中包含代碼段,你可以創(chuàng)建一個(gè)在運(yùn)行時(shí)按需加載的模塊。這個(gè)從根本上提高了性能,因?yàn)樵趩?dòng)過(guò)程中不需要把所有東西都發(fā)送到客戶端。System.import將模塊名作為參數(shù),并返回一個(gè)Promise對(duì)象。require.ensure獲取依賴關(guān)系的列表,回調(diào)函數(shù)以及可選的模塊名。
如果應(yīng)用程序的某一部分具有很大的依賴關(guān)系,則應(yīng)用程序的其余部分就不需要了,最好的方式就是拆分到各個(gè)模塊中去。我們通過(guò)新建一個(gè)需要依賴d3的模塊dashboard.js來(lái)證明這點(diǎn)。

npm install d3 --save
// src/dashboard.js
import * as d3 from 'd3'

console.log('Loaded!', d3)

export const draw = () => {
  console.log('Draw!')
}

app.js的頂部引入dashboard.js

// ...

const routes = {
  dashboard: () => {
    System.import('./dashboard').then((dashboard) => {
      dashboard.draw()
    }).catch((err) => {
      console.log("Chunk loading failed")
    })
  }
}

// demo async loading with a timeout
setTimeout(routes.dashboard, 1000)

因?yàn)槲覀兗虞d了異步模塊,我們需要在配置文件中增加output.publicPath屬性,因此webpack知道去哪里獲取。

// webpack.config.js

const config = {
  // ...
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/dist/',
    filename: '[name].bundle.js'
  },
  // ...
}

運(yùn)行npm build操作,你會(huì)看到一個(gè)新的神秘的打包文件0.bundle.js。

注意webpack為了保持誠(chéng)實(shí),通過(guò)凸現(xiàn)[big]的包來(lái)讓你保持關(guān)注。
這個(gè)0.bundle.js將會(huì)通過(guò)JSONP的請(qǐng)求按需加載,所以從文件目錄中獲取將不在有效,我們需要啟動(dòng)一個(gè)服務(wù)來(lái)獲取文件。

python -m SimpleHTTPServer 8001

打開(kāi)瀏覽器,輸入http://localhost:8001/
加載一秒鐘后,你會(huì)獲得一個(gè)GET請(qǐng)求,我們動(dòng)態(tài)生成了/dist/0.bundle.js文件,在控制臺(tái)上打印除了"Loaded!",成功!

webpack開(kāi)發(fā)服務(wù)器

當(dāng)文件改變時(shí),實(shí)時(shí)地重新加載能提高開(kāi)發(fā)者的開(kāi)發(fā)效率。只要安裝它,并且以webpack-dev-server的形式啟動(dòng),就可以體驗(yàn)啦。

npm install webpack-dev-server@2.2.0-rc.0 --save-dev

修改package.json中的start腳本:

"start": "webpack-dev-server --inline",

重新運(yùn)行npm start,在瀏覽器中打開(kāi)http://localhost:8080
試著去改變src目錄中任何文件,如改變people.js中的任意一個(gè)名字,或者style.scss中的任意樣式,去看看它如何實(shí)時(shí)改變。

熱模塊替換(熱更新)

如果你對(duì)實(shí)時(shí)重新加載印象深刻,那么hot module replacement(HMR)一定會(huì)讓你吃驚不已。

現(xiàn)在是2017年了,你在工作中已經(jīng)可以在單頁(yè)面應(yīng)用中使用全局狀態(tài)了。在開(kāi)發(fā)過(guò)程中,你可能會(huì)對(duì)組件進(jìn)行許多小的修改,并且希望能在瀏覽器中看到修改后生成的結(jié)果,這樣可以實(shí)時(shí)去更改。但是通過(guò)刷新頁(yè)面或者實(shí)時(shí)熱更新并不能改變?nèi)值臓顟B(tài),你就必須重頭開(kāi)始。但是HMR永遠(yuǎn)地改變了這一問(wèn)題。

最后對(duì)package.json中的start腳本做修改:

"start": "webpack-dev-server --inline --hot",

app.js中告訴webpack去接受這個(gè)模塊以及對(duì)應(yīng)依賴的熱更新。

if (module.hot) {
  module.hot.accept()
}

// ...

注意:webpack-dev-server --hot設(shè)置了module.hottrue,但只是在開(kāi)發(fā)過(guò)程中。當(dāng)以生產(chǎn)模式打包時(shí),module.hot被設(shè)成了false,這樣這些包就被從結(jié)果中抽離了。

webpack.config.js中增加一個(gè)NamedModulesPlugin插件,去改善控制臺(tái)的記錄功能。

plugins: [
  new webpack.NamedModulesPlugin(),
  // ...
]

最后我們?cè)陧?yè)面中增加一個(gè)<input>元素,我們可以在里面增加一些文字,用來(lái)確保我們更改自己模塊時(shí)頁(yè)面不會(huì)刷新。

<body>
  <input />
  <div id="root"></div>
  ...

運(yùn)行npm start重啟服務(wù),觀察熱更新如何工作吧。

為了實(shí)驗(yàn),在input框中輸入“HMR Rules”,接著改變一個(gè)people.js中的名字,你會(huì)發(fā)現(xiàn)頁(yè)面在不刷新也能做出修改,而忽略input的狀態(tài)。

這只是一個(gè)簡(jiǎn)單的例子,但是希望你能看到其廣泛的用途。在諸如React的開(kāi)發(fā)模式中,你可能有很多"啞巴"組件是與他們的狀態(tài)分離開(kāi)的,通過(guò)熱更新,這些組件將不會(huì)失去狀態(tài),也能實(shí)時(shí)更新,因此你將獲得及時(shí)的反饋。

熱更新CSS

修改style.scss文件中<pre>元素的背景顏色,你發(fā)現(xiàn)他并沒(méi)有被HMR替換。

pre {
  background: red;
}

事實(shí)證明當(dāng)你使用style-loader時(shí),CSS的熱更新將會(huì)免費(fèi)為你提供而不需要你做任何特殊處理。我們只需要斷開(kāi)CSS模塊與最終抽取的包之間的鏈接,這個(gè)包是無(wú)法被替換的。

如果我們將Sass規(guī)則恢復(fù)到原始狀態(tài),并從插件列表中刪除extractCSS,那么您也可以看到Sass的熱重新加載。

{
  test: /\.scss$/,
  loader: ['style-loader', 'css-loader','sass-loader']
}

HTTP/2

使用像webpack這樣的模塊打包工具的主要好處之一是,您可以通過(guò)控制資源的構(gòu)建方式以及在客戶端上的獲取方式,從而幫助你提高性能。多年以來(lái),它被認(rèn)為是最佳實(shí)踐,通過(guò)連接文件減少客戶端請(qǐng)求?,F(xiàn)在還是有效,但是HTTP2在單一請(qǐng)求中發(fā)送多文件,因此連接文件的方式不不再是"銀彈"。你的應(yīng)用程序?qū)嶋H上可以從多個(gè)小文件單獨(dú)緩存,但客戶端可以獲取單個(gè)更改的模塊,而不必再次獲取大部分相同內(nèi)容的整個(gè)包。

Webpack的創(chuàng)始人Tobias Koppers的撰寫(xiě)了一篇內(nèi)容豐富的帖子,解釋了為什么打包仍然很重要,即使在HTTP/2時(shí)代。

想了解更多請(qǐng)參考webpack & HTTP/2

寫(xiě)在結(jié)尾的話

我真心希望你已經(jīng)發(fā)現(xiàn)這個(gè)介紹webpack 2的文章對(duì)你有幫助,并能夠開(kāi)始很好使用它。圍繞webpack的配置,加載程序和插件可能需要一些時(shí)間,但是了解這個(gè)工具的工作原理后會(huì)對(duì)你有很大幫助。

文檔仍在進(jìn)行更新中,但如果您想將現(xiàn)有的Webpack1項(xiàng)目移到Webpack2,則可以參考Migrating from v1 to v2

webpack是否是你打包的選擇,從評(píng)論中你就可以知曉。

本文由Scott MolinariJoan YinJoyce Echessa進(jìn)行了同行評(píng)審。 感謝SitePoint的同行評(píng)議人員,使SitePoint內(nèi)容成為最棒的內(nèi)容!

本文翻譯自A Beginner’s Guide to Webpack 2 and Module Bundling
翻譯者:Allen Gong

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容