參考資料:https://www.webpackjs.com/(中文文檔) https://www.webpackjs.com/(官方文檔)
首先有必要說明一下,本文側重講解webpack基本配置屬性,不附帶實例,將會以通俗易懂的形式地講解;如若需要實例進行相關練習,可將本文作為理論基礎;
Webpack是前端項目自動化構建工具,本質上,webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關系圖(dependency graph),其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle。(官網定義)。
那么用我們人話來說:webpack是一個前端模塊化的解決方案,更側重點打包,可以把開發中的資源文件(圖片、js文件、css文件等)看成是一個個的模塊,然后通過webpack提供的loader(加載器)和plugins(插件)來進行處理、合並以及壓縮,打包成符合生產環境、體積更小的文件資源,以方便提升瀏覽器的渲染速度;
首先我們要理解一下webpack的四大核心概念:
入口(entry)
出口(output)
loader(加載器)
plugins(插件)
入口(entry):
webpack入口指的是通過配置來指示webpack的入口文件,即從哪里開始,我們可以在webpack中配置entry屬性,來指定入口文件的路徑;
我們可以看一個簡單的案例:
//必須將模塊拋出webpack才能訪問得到 module.exports = { //entry屬性指定入口文件 值為相對路徑 entry: './src/app.js' }
出口(output):
出口即告訴webpack在哪里輸出它所創建的bundles,以及如何命名這些文件,輸出的文件目錄路徑;也就是說在你用webpack打包的時候可以通過添加output屬性,來設置最終經過webpack打包輸出后的文件名以及輸出路徑;
//引入node的path模塊 const path = require('path'); module.exports = { // webpack執行入口文件 entry: './src/app.js', //出口 output: { // 把所有依賴的模塊合並輸出到一個 bundle.js 文件 filename: 'bundle.js', // 輸出文件都放到 dist 目錄下 //__dirname是node環境中全局變量,表示當前目錄 path: path.resolve(__dirname, './dist'), } };
加載器(loader):
loader是讓webpack能夠去處理一些非Javscript類型的文件(webpack自身只能夠識別原生JS和ES5),loader可以將所有類型的文件轉為webpack能處理的有效模塊,然后就可以通過webpack的打包能力,對這些文件進行處理;loader的配置有兩個選項:
test:一般都是正則表達式,用於匹配文件類型;
use:可以是key:value的形式也可以是數組,用來告訴webpack使用什么loader來加載文件
//引入node的path模塊 const path = require('path'); module.exports = { // webpack執行入口文件 entry: './src/app.js', //出口 output: { // 把所有依賴的模塊合並輸出到一個 bundle.js 文件 filename: 'bundle.js', // 輸出文件都放到 dist 目錄下 //__dirname是node環境中全局變量,表示當前目錄 path: path.resolve(__dirname, './dist'), } //模塊關鍵字,加載器需要在這里進行配置 module:{ //rules為數組,保存每個加載器的配置 rules:[ { //test屬性必須配置,值為正則表達式,用於匹配文件 test:/\.css$/, // 對同一個文件引入多個loader的方法 use:[ //loader為loader加載器的名稱,必須配置,值為字符串 {loader:"style-loader"}, {loader:"css-loader"} ], //過濾,排除node_module目錄下的文件 exclude:/node_module/, //指定匹配文件的范圍 指定/demo/目錄下的.css文件進行匹配 include:/demo/ } ] } };
webpack中規定,在webpack中定義loader時,需要定義在module.rules中,否則會報錯;test和use兩個屬性分別指定了匹配文件的規則和用什么loader來處理,這兩個屬性都是必選的,exclude、include分別表示過濾(不處理)某個文件中的文件和指定(處理)某個文件夾中的文件,這兩個屬性都是可選項;
插件(plugins):
loader 被用於轉換某些類型的模塊,而插件則可以用於執行范圍更廣的任務。插件的范圍包括,從打包優化和壓縮,一直到重新定義環境中的變量。插件接口功能極其強大,可以用來處理各種各樣的任務。要使用某個插件,你需要require(引入)插件,然后添加到plugins數組中,多數插件可以通過選項option來自定義
//引入node的path模塊 const path = require('path'); //引入extract-text-webpack-plugin插件 const ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = { // webpack執行入口文件 entry: './src/app.js', //出口 output: { // 把所有依賴的模塊合並輸出到一個 bundle.js 文件 filename: 'bundle.js', // 輸出文件都放到 dist 目錄下 //__dirname是node環境中全局變量,表示當前目錄 path: path.resolve(__dirname, './dist'), } //模塊關鍵字,加載器需要在這里進行配置 module:{ //rules為數組,保存每個加載器的配置 rules:[ { //test屬性必須配置,值為正則表達式,用於匹配文件 test:/\.css$/, // 對同一個文件引入多個loader的方法 use:[ //loader為loader加載器的名稱,必須配置,值為字符串 {loader:"style-loader"}, {loader:"css-loader"} ], //過濾,排除node_module目錄下的文件 exclude:/node_module/, //指定匹配文件的范圍 指定/demo/目錄下的.css文件進行匹配 include:/demo/ } ] } //配置插件 plugins: [ new ExtractTextPlugin({ //自定義配置插件選項 // 從 .js 文件中提取出來的 .css 文件的名稱 filename: `[name]_[md5:contenthash:hex:8].css`, }), ] };
上面就是webpack的四大核心概念,下面我們來介紹一些常用的插件:
loader處理css和Sass:
默認情況下webpack是處理不了CSS的代碼的,但是我們可以通過webpack的loader加載器來處理;
module.exports = { entry: './src/app.js', output: { path: __dirname + '/dist', filename: 'app.bundle.js' }, module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] } ] } };
在日常開發中,我們只需要在webpack.config.js文件中寫上上面的配置代碼即可讓webpack來處理CSS代碼和Sass代碼;
webpack-dev-server:
webpack-dev-server是webpack的一個常用插件,可以用來在本地上開啟服務、啟動瀏覽器並且可以實時監聽文件修改;
module.exports = { entry: './src/app.js', ... //進行webpack-dev-server插件配置 devServer: { //端口號,默認8080,可以自定義修改 port: 9000, //運行webpack-dev-server的時候自動打開瀏覽器 open: true }, ... };
source-map調試:
開發總是離不開調試,但是我們用webpack給項目打包了之后,我們是很不方便找到錯誤或者問題所在的,當然webpack也想到了這一點,因此webpack給我們提供了source-map來進行調試;
devtool選項
source-map
配置結果
在一個單獨的文件中產生一個完整且功能完全的文件。這個文件具有最好的source map,但是它會減慢打包速度;
devtool選項
cheap-module-source-map
配置結果
在一個單獨的文件中生成一個不帶列映射的map,不帶列映射提高了打包速度,但是也使得瀏覽器開發者工具只能對應到具體的行,不能對應到具體的列(符號),會對調試造成不便;
devtool選項
eval-source-map
配置結果
使用eval打包源文件模塊,在同一個文件中生成干凈的完整的source map。這個選項可以在不影響構建速度的前提下生成完整的sourcemap,但是對打包后輸出的JS文件的執行具有性能和安全的隱患。在開發階段這是一個非常好的選項,在生產階段則一定不要啟用這個選項;
devtool選項
cheap-module-eval-source-map
配置結果
這是在打包文件時最快的生成source map的方法,生成的Source Map會和打包后的JavaScript文件同行顯示,沒有列映射,和eval-source-map選項具有相似的缺點;
綜上所述,從上到下打包速度越來越快,不過同時帶來的副作用也越多,較快的打包速度的后果就是對打包后的文件的的執行有一定影響。在中小型項目中,eval-source-map是一個比較不錯的選擇;
cheap-module-eval-source-map方法構建速度更快,但是不利於調試,推薦在大型項目考慮時間成本時使用。
module.exports={ devtool:"eval-source-map", }
在webpack打包之后,如果報錯我們是看不到源文件的,因為此時文件已經被webpack打包了,這很不方便我們的開發調試,source-map就是用來解決這個問題的,通過添加配置devtool:"eval-source-map"這一行簡單的代碼,我們即可在調試的時候看到我們的源文件進行調試;