若是2020年做爲一個前端開發你還不知道 Webpack
是什麼,真的就要考慮回爐重造了。不少人可能會得意洋洋,嘴角上揚回答:這誰不知道,不就是一個項目構建工具嗎,咱們的項目如今都用着了。這我固然信,可是若是讓你認真介紹 Webpack
核心的概念有哪些,底層的原理是怎麼樣的,那麼你還能淡定地娓娓道來嗎?以前的我可能也跟大部分人同樣,只停留在簡單會用,知道的水平,並且幾乎每一個經歷過的項目也都在使用,也知道 create-react-app
和 vue-cli
底層都是依賴 webpack
,可是我以爲做爲一個想要更進階的前端工程師,你須要掌握的更多。這也是爲何我想寫這篇文章的緣由之一,這是也是我從新學習 Webpack
系列的第一篇:Webpack概述。javascript
先看官網的介紹:css
webpack is a static module bundler for modern JavaScript applications.html
翻譯過來大概的意思就是 Webpack
是一個現代的 JavaScript
應用 模塊 打包器。首先咱們要清楚它的定位是爲 JavaScript 應用
服務的,有時候咱們開發一些組件庫、工具庫,開發完後也須要有一個打包構建、上線這樣一個過程,這種類型的項目咱們通常不用 Webpack
,而是用 Rollup
這樣的工具。第二,咱們要注意的是,上面我特地加粗的另外一個關鍵詞:模塊。那麼在 Webpack
眼裏到底哪些是模塊?前端
隨着 Commonjs
的出現,CMD
和 AMD
模塊思想的誕生,ES Module
逐漸成爲標準, JavaScript
終於進入了模塊化編程的時代。模塊化編程使得咱們更好的組織JS代碼,合理的劃分也使得代碼更容易調試、測試。NodeJS誕生的時候就有本身的模塊化,而Web的模塊進展一直比較緩慢。與Node.js模塊相比,webpack模塊能夠用多種方式表達模塊之間的依賴關係。下面是一些例子:vue
import
;require()
;define
和 require
;@import
;url(...)
和 HTML 中的<img src="...">
。Webpack
也支持各類各樣的模塊,下面是一些經常使用的例子:java
咱們知道 Webpack
主要是一個 JavaScript
的打包器,那麼它怎麼識別和處理其它的非JS模塊呢?這就牽涉到 Webpack
最重要的概念: Loader
,下面咱們開始介紹 Webpack
的核心概念。react
入口代表了 Webpack
從哪一個模塊開始構建內部的依賴圖,Webpack
將找出入口所依賴的其它模塊和庫。它的默認值是 src/index.js
,你也能夠經過配置指定不一樣的路徑:webpack
module.exports = {
entry: './path/to/my/entry/file.js'
};
複製代碼
你也能夠配置多個入口,在開發多頁面應用的時候就可能須要配置多個入口:web
module.exports = {
entry: {
app: './src/app.js',
adminApp: './src/adminApp.js'
}
};
複製代碼
既然有入口,那就有出口,出口選項告訴 Webpack
構建好的 bundles
放在哪一個目錄下以及怎麼命名輸出的文件。默認值是:./dist/main.js
,輸出的文件默認都放在 dist
目錄下。固然你也能夠自定義本身的 output
選項:正則表達式
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
複製代碼
在上面的例子中,output.path
告訴 Webpack
輸出的文件放在什麼目錄下,output.filename
指明生成的文件命名規則。
前面咱們提到了一切資源(字體文件、圖片、CSS、預編譯器Sass等)甚至 Vue
組件在 Webpack
中都被當成模塊來處理,可是 Webpack
自身其實只是一個 JavaScript Bundler
,它只認識JS模塊和JSON文件。因爲在一個複雜的Web應用中,咱們不僅有JS模塊,也有HTML、CSS、圖片等資源,若是使用框架,還須要 Vue SFC
,React jsx
等,因此這時候就須要 Loaders
出馬了。Loaders
可使得 Webpack
可以處理各類類型的模塊,處理完後再把它們加入到依賴圖中。
每一個 loader
配置主要有兩個選項:
test
選項,確認哪些些文件將被 loader
轉換,通常是一個正則表達式;use
選項,代表哪些 loaders 將被用來轉換文件。下面看一個例子:
module.exports = {
output: {
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{ test: /\.js$/, use: 'babel-loader' }
]
}
};
複製代碼
上面的例子,定義了一個 loader
轉換規則,它告訴 Webpack
編譯器,當發現js
文件的時候,使用 babel-loader
進行轉換。
咱們還能夠配置多個 loader
,好比下面這個例子:
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
// style-loader
{ loader: 'style-loader' },
// css-loader
{
loader: 'css-loader',
options: {
modules: true
}
},
// sass-loader
{ loader: 'sass-loader' }
]
}
]
}
};
複製代碼
上面這個例子告訴 Webpack
編譯器,當遇到以 .scss
結尾的文件,先用 sass-loader
處理,接着再用 css-loader
轉化,最後使用 style-loader
完成此類文件的處理,它的處理順序是從後往前。
Loaders
幫助 Webpack
處理不一樣類型的文件和模塊,而插件被用來擴展 Webpack
的功能,使得Webpack
更增強大,插件能夠用來優化 bundle
(壓縮文件、tree shaking、code split等)、管理靜態資源和注入環境變量。
使用一個插件以前,首先經過 require
引入插件,而後將它添加到 plugins
選項數組中,大部分插件支持一些選項配置。因爲能夠在配置中爲不一樣的需求屢次使用插件,因此你須要經過使用new操做符調用插件來建立它的實例:
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
module.exports = {
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({template: './public/index.html'})
]
};
複製代碼
在上面的例子中,html-webpack-plugin
將會爲你的應用生成一個 html
文件,而且這個文件會被自動注入 Webpack
處理生成的全部 bundle
。
在 Webpack
中配置插件仍是比較簡單的,關鍵是你要了解生態中有哪些優秀的插件能夠直接拿來使用,挑選出適合你本身項目的插件組合,在沒有合適的插件支撐你的業務需求時,你也選擇能夠開發本身的 Webpack
插件。
以上是我以爲在 Webapck
中比較核心的概念,這些是你學習 Webpack
必須掌握的概念,Entry
和 Output
可能相對簡單,Loaders
和 Plugins
機制是核心中的核心,其底層的原理也值得仔細探究,後續的文章中我會對其進行分析。
在官方文檔中,還提到兩個點能夠注意一下。一個是 mode
,經過設置不一樣的值,告訴 Webpack
當前是開發環境仍是生產環境。其主要的值有 development
、production
和 none
,對於每一個選項, Wepack
都會在底層作相應環境的一些優化,它的默認值是:production
。
第二個點是 Browser Compatibility
,也就是瀏覽器兼容性。webpack支持全部兼容es5的瀏覽器(不支持IE8及如下版本)。Webpack
中的 import()
和 require.ensure()
須要支持Promise
,若是你想支持較老的瀏覽器,須要 引入 Polyfill
,想要了解更多,能夠查看:load polyfill。