首頁 > 軟體

webpack安裝設定及使用教學詳解

2022-06-24 22:01:05

一、webpack介紹

1、由來

由於前端之前js、css、圖片檔案需要單獨進行壓縮和打包,這樣團隊人員處理很繁瑣,然後 Instagram 團隊就想讓這些工作自動化,然後webpack應運而生。

2、介紹

webpack是一個模組打包器(module bundler),webpack視HTML,JS,CSS,圖片等檔案都是一種 資源 ,每個資原始檔都是一個模組(module)檔案,webpack就是根據每個模組檔案之間的依賴關係將所有的模組打包(bundle)起來。

3、作用

  • 對 CommonJS 、 AMD 、ES6的語法做了相容
  • 對js、css、圖片等資原始檔都支援打包(適合團隊化開發)
  • 比方你寫一個js檔案,另外一個人也寫一個js檔案,需要合併很麻煩,現在交給webpack合併很簡單
  • 有獨立的組態檔webpack.config.js
  • 可以將程式碼切割成不同的chunk,實現按需載入,降低了初始化時間
  • 具有強大的Plugin(外掛)介面,大多是內部外掛,使用起來比較靈活
  • ……

4、拓展說明

CommonJS、AMD、CMD是用於JavaScript模組管理的三大規範,CommonJS定義的是模組的同步載入,是一個更偏向於伺服器端的規範(也可以在瀏覽器中使用),主要用於Nodejs,根據CommonJS規範,一個單獨的檔案就是一個模組,載入模組使用require()方法,該方法讀取一個檔案並執行,最後返回檔案內部的exports物件。

AMD和CMD則是定義模組非同步載入適用於瀏覽器端,都是為了 JavaScript 的模組化開發,(這裡說一下為什要有非同步載入,因為瀏覽器如果使用common.js同步載入模組的話,就會導致效能等問題,所以針對這個問題,又出了一個規範,這個規範可以實現非同步載入依賴模組)

AMD規範會提前載入依賴模組,AMD規範是通過requireJs 在推廣過程中對模組定義的規範化產出。

(AMD 規範:https://github.com/amdjs/amdjs-api/wiki/AMD

CMD規範會延遲載入依賴模組, CMD 規範是 SeaJs 在推廣過程中對模組定義的規範化產出。

(CMD規範:https://github.com/seajs/seajs/issues/242

AMD規範和CMD規範的區別

  • 對於依賴的模組,AMD 是提前執行,CMD 是延遲執行。不過 RequireJS 從 2.0 開始,也改成可以延遲執行(根據寫法不同,處理方式不同)
  • CMD 推崇依賴就近,AMD 推崇依賴前置
  • AMD 的 API 預設是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一。比如 AMD 裡,require 分全域性 require 和區域性 require,都叫 require。CMD 裡,沒有全域性 require,而是根據模組系統的完備性,提供 seajs.use 來實現模組系統的載入啟動。CMD 裡,每個 API 都簡單純粹

webpack和gulp的區別

  • gulp是前端自動化構建工具,強調的是前端開發的工作流程,我們可以通過設定一系列的task,定義task處理的事情(程式碼壓縮、合併、編譯、瀏覽器實時更新等),然後定義執行順序,來讓gulp執行這些task,從而構建專案的整個前端開發流程,自動化構建工具並不能把所有模組打包到一起,也不能構建不同模組之間的依賴關係。
  • webpack是 JavaScript 應用程式的模組打包器,強調的是一個前端模組化方案,更側重模組打包,我們可以把開發中的所有資源(圖片、js檔案、css檔案等)都看成模組,通過loader(載入器)和plugins(外掛)對資源進行處理,打包成符合生產環境部署的前端資源。

5、webpack整體認知

(1)、webpack的核心概念分為 入口(Entry)、載入器(Loader)、外掛(Plugins)、出口(Output);

  • 入口(Entry):入口起點告訴 webpack 從哪裡開始,並根據依賴關係圖確定需要打包的檔案內容
  • 載入器(Loader):webpack 將所有的資源(css, js, image 等)都看做模組,但是 webpack 能處理的只是 JavaScript,因此,需要存在一個能將其他資源轉換為模組,讓 webpack 能將其加入依賴樹中的東西,它就是 loader。loader用於對模組的原始碼進行轉換。loader 可以使你在 import 或"載入"模組時預處理檔案。因此,loader 類似於其他構建工具中“任務(task)”,並提供了處理前端構建步驟的強大方法。
rules: [
    {
        test: /.(js|jsx)$/,
        use: 'babel-loader'
    }
]

外掛(Plugins):loader 只能針對某種特定型別的檔案進行處理,而 plugin 的功能則更為強大。在 plugin 中能夠介入到整個 webpack 編譯的生命週期,Plugins用於解決 loader 無法實現的其他事情,也就是說loader是預處理檔案,那plugin 就是後處理檔案。

對loader打包後的模組檔案(bundle.js)進行二次優化處理,例如:程式碼壓縮從而減小檔案體積

提供輔助開發的作用:例如:熱更新(瀏覽器實時顯示)

plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
]

二、webpack安裝

1、安裝node

使用 node -v 命令檢查版本

2、安裝cnpm

https://npmmirror.com/

npm install -g cnpm --registry=https://registry.npm.taobao.org

使用 cnpm -v 命令檢查版本

3、安裝nrm的兩種方法

https://www.npmjs.com/package/nrm

nrm可以幫助我們切換不同的NPM源的快捷開關,可以切換的NPM源包括:npm,cnpm,taobao, rednpm, npmMirror , edunpm

#第一種方法(由於是外網存取進行安裝,可能會被牆)
npm install -g nrm 
#第二種方法(國內的淘寶映象,存取穩定,推薦)
cnpm install -g nrm 
  • 使用 nrm - V 命令檢查版本(注意這裡的 V 是大寫的)
  • 使用nrm ls 命令可以檢視當前可以可以切換的 NPM源
  • 使用 npm use cnpm 命令 指定要使用的哪種NPM源

4、安裝webpack

全域性安裝

npm install --global webpack

在專案中安裝最新版本或特定版本,分別執行以下命令:

npm install --save-dev webpack
npm install --save-dev webpack@<version>

三、webpack設定

搭建專案結構

webpack(專案總目錄)

dist

src

js

moudle1.js

function sum(x,y){
    return x + y;
}
// 匯出 sum 函數
module.exports = sum;

main.js

// 1、獲取index.html中的dom物件
var first = document.getElementById('first');
var btn = document.getElementById('btn');
var two = document.getElementById('two');
var res = document.getElementById('res');
btn.onclick = function(){
                var firstValue = parseFloat(first.value);
                var twoValue = parseFloat(two.value);
                //2、獲取 module1.js中的 sum函數
                //http://www.ruanyifeng.com/blog/2015/05/require.html
                var sum = require('./module1.js');
                res.value = sum(firstValue,twoValue);
            }

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text" id="first">
    <input type="button" id="btn" value="+">
    <input type="text" id="two">
    <input type="button" id="btn" value="=">
    <input type="text" id="res">
    <script src="./dist/js/bulid.js"></script>
</body>
</html>

webpack.config.js(手動建立)

const path = require('path');  // 首先要引入node.js中path 模組,用於處理檔案與目錄的路徑
// const 命令宣告一個唯讀的常數,一旦宣告,值不可以改變,改變會報錯;只宣告不賦值也會報錯
// 常數儲存的是一個不可以變化的變數。
// 
module.exports = {
    entry:'./src/./js/main.js', // 指定入口檔案
    output:{
        path: path.resolve(__dirname, './dist/js'), // 指定出口檔案的路徑目錄
        filename: 'bulid.js' // 制定出口檔案的名稱
    },

1、初始化一個專案(會建立一個package.json檔案)

npm init

2、在當前的專案中安裝Webpack作為依賴包

npm install --save-dev webpack

說明:

--save :將設定資訊儲存到package.json中,

同時 --save :也是專案生產環境,專案發布之後還依賴的東西,儲存在dependencies

例如:如果你用了 jQuery,由於釋出之後還是依賴jQuery,所以是dependencies

--save-dev :是專案開發環境依賴的東西,儲存在devDependencies中

例如:寫 ES6 程式碼,如果你想編譯成 ES5 釋出那麼 babel 就是devDependencies

3、當前專案結構

4、實現CSS打包

npm install css-loader style-loader --save-dev
#或者
cnpm install css-loader style-loader --save-dev

在src—>css目錄中新建main.css

#first{
    border: 1px solid red;
}

在webpack.config.js中設定相關的loader

const path = require('path');  // 首先要引入node.js中path 模組,用於處理檔案與目錄的路徑
// const 命令宣告一個唯讀的常數,一旦宣告,值不可以改變,改變會報錯;只宣告不賦值也會報錯
// 常數儲存的是一個不可以變化的變數。
// 
module.exports = {
    entry:'./src/./js/main.js', // 指定入口檔案
    output:{
        path: path.resolve(__dirname, './dist/js'), // 指定出口檔案的路徑目錄
        filename: 'bulid.js' // 制定出口檔案的名稱
    },
    module:{
        rules:[
        // 在webpack2中,loaders 被替換成了 rules 其實就是loader的規則
            {
                test: /.css$/,
                use: [ 'style-loader', 'css-loader' ]
                // test 說明了當前 loader 能處理那些型別的檔案
                // use 則指定了 loader 的型別。
                // 注意:陣列中的loader不能省略擴充套件名
            }
        ]
    }
}

在main.js中獲取css目錄中的main.css檔案

// 1、獲取index.html中的dom物件
var first = document.getElementById('first');
var btn = document.getElementById('btn');
var two = document.getElementById('two');
var res = document.getElementById('res');
    btn.onclick = function(){
        var firstValue = parseFloat(first.value);
        var twoValue = parseFloat(two.value);
        //2、獲取 module1.js中的 sum函數
        //http://www.ruanyifeng.com/blog/2015/05/require.html
        var sum = require('./module1.js');
        res.value = sum(firstValue,twoValue);
    }
    // 3、獲取css目錄中的main.css檔案
    require('../css/main.css');

在終端中輸入 webpack命令進行css檔案打包

5、實現SCSS打包

在src目錄中新建 sass目錄--> scss1.scss

// scss1.scss檔案
$color:purple;
#two{
    border:1px solid $color; 
}

安裝對應的loader

npm install sass-loader node-sass webpack --save-dev

或者

cnpm install sass-loader css-loader style-loader node-sass webpack --save-dev

在webpack.config.js中設定相關的loader

   const path = require('path');  // 首先要引入node.js中path 模組,用於處理檔案與目錄的路徑
   // const 命令宣告一個唯讀的常數,一旦宣告,值不可以改變,改變會報錯;只宣告不賦值也會報錯
   // 常數儲存的是一個不可以變化的變數。
   // 
   module.exports = {
       entry:'./src/./js/main.js', // 指定入口檔案
       output:{
           path: path.resolve(__dirname, './dist/js'), // 指定出口檔案的路徑目錄
           filename: 'bulid.js' // 制定出口檔案的名稱
       },
       module:{
           rules:[
           // 在webpack2中,loaders 被替換成了 rules 其實就是loader的規則
           //  實現 css 打包
               {
                   test: /.css$/,
                   use: [ 'style-loader', 'css-loader' ]
                   // test 說明了當前 loader 能處理那些型別的檔案
                   // use 則指定了 loader 的型別。
                   // 注意:陣列中的loader不能省略擴充套件名
               },
               {
                   test: /.scss$/,
                   // 注意 是sass-loader ,不是 scss-loader
                   use: [ 'style-loader', 'css-loader', 'sass-loader' ]
               }
           ]
       }
   }

在js目錄中 main.js裡面引入 scss1.scss

// 1、獲取index.html中的dom物件
var first = document.getElementById('first');
var btn = document.getElementById('btn');
var two = document.getElementById('two');
var res = document.getElementById('res');
btn.onclick = function(){
    var firstValue = parseFloat(first.value);
    var twoValue = parseFloat(two.value);
    //2、獲取 module1.js中的 sum函數
    //http://www.ruanyifeng.com/blog/2015/05/require.html
    var sum = require('./module1.js');
    res.value = sum(firstValue,twoValue);
}
// 3、獲取css目錄中的main.css檔案
require('../css/main.css');
// 4、獲取sass目錄中的scss1.scss檔案
require('../sass/scss1.scss');

在終端中輸入 webpack命令進行scss檔案打包

6、實現Less打包

安裝

cnpm install --save-dev
cnpm install less less-loder css-loader style-loader  webpack --save-dev

或者

cnpm install less-loader less --save-dev在webpack.config.js中設定相關的loader

在在src目錄中新建less目錄--> less1.less

  • @color:blue;
    #res{
        border:1px dashed blue;
    }
    

在webpack.config.js中設定相關的loader

const path = require('path');  // 首先要引入node.js中path 模組,用於處理檔案與目錄的路徑
// const 命令宣告一個唯讀的常數,一旦宣告,值不可以改變,改變會報錯;只宣告不賦值也會報錯
// 常數儲存的是一個不可以變化的變數。
// 
module.exports = {
    entry:'./src/./js/main.js', // 指定入口檔案
    output:{
        path: path.resolve(__dirname, './dist/js'), // 指定出口檔案的路徑目錄
        filename: 'bulid.js' // 制定出口檔案的名稱
    },
    module:{
        rules:[
        // 在webpack2中,loaders 被替換成了 rules 其實就是loader的規則
            //  實現 css 打包
            {
                test: /.css$/,
                use: [ 'style-loader', 'css-loader' ]
                // test 說明了當前 loader 能處理那些型別的檔案
                // use 則指定了 loader 的型別。
                // 注意:陣列中的loader不能省略擴充套件名
            },
            // 實現 scss 打包
            {
                test: /.scss$/,
                // 注意 是sass-loader ,不是 scss-loader
                use: [ 'style-loader', 'css-loader', 'sass-loader' ]
            },
            // 實現 less 打包
            {
                test: /.less$/,
                use: [ 'style-loader', 'css-loader', 'less-loader' ]
            }
        ]
    }
}

在js目錄中 main.js裡面引入 less1.less檔案

// 5、獲取less目錄中的less1.less檔案
require('../less/less1.less');

7、實現打包url資源(圖片、gif、圖示等)功能

在src 目錄中 新建imgs目錄,放入兩張不同大小的圖片

在index.html中新增 <div id="bg1"></div> <div id="bg2"></div>

在mian.css中新增

// mian.css檔案
#bg1{
    width: 200px;
    height: 200px;
    background: url('../imgs/bxg.jpg');
}
#bg2{
    width: 200px;
    height: 200px;
    background: url('../imgs/web.jpg') no-repeat;
}

使用注意事項

1.如果我們希望在頁面引入圖片(包括img的src和background的url)。當我們基於webpack進行開發時,引入圖片會遇到一些問題。

​2. 其中一個就是參照路徑的問題。拿background樣式用url引入背景圖來說,我們都知道,webpack最終會將各個模組打包成一個檔案,因此我們樣式中的url路徑是相對入口html頁面的,而不是相對於原始css檔案所在的路徑的。這就會導致圖片引入失敗。這個問題是用file-loader解決的,file-loader可以解析專案中的url引入(不僅限於css),根據我們的設定,將圖片拷貝到相應的路徑,再根據我們的設定,修改打包後檔案參照路徑,使之指向正確的檔案。

3.​ 另外,如果圖片較多,會發很多http請求,會降低頁面效能。這個問題可以通過url-loader解決。url-loader會將引入的圖片編碼,生成dataURl。相當於把圖片資料翻譯成一串字元。再把這串字元打包到檔案中,最終只需要引入這個檔案就能存取圖片了。當然,如果圖片較大,編碼會消耗效能。因此url-loader提供了一個limit引數,小於limit位元組的檔案會被轉為DataURl,大於limit的還會使用file-loader進行copy。

4.​ url-loader和file-loader是什麼關係呢?簡答地說,url-loader封裝了file-loader。url-loader不依賴於file-loader,即使用url-loader時,只需要安裝url-loader即可,不需要安裝file-loader,因為url-loader內建了file-loader。通過上面的介紹,我們可以看到,url-loader工作分兩種情況:

  • 1.檔案大小小於limit引數,url-loader將會把檔案轉為DataURL;
  • 2.檔案大小大於limit,url-loader會呼叫file-loader進行處理,引數也會直接傳給file-loader。因此我們只需要安裝url-loader即可。

安裝

cnpm install
cnpm install url-loader file-loader --save-dev

在webpack.config.js中設定相關的loader

const path = require('path');  // 首先要引入node.js中path 模組,用於處理檔案與目錄的路徑
// const 命令宣告一個唯讀的常數,一旦宣告,值不可以改變,改變會報錯;只宣告不賦值也會報錯
// 常數儲存的是一個不可以變化的變數。
// 
module.exports = {
    entry:'./src/./js/main.js', // 指定入口檔案
    output:{
        path: path.resolve(__dirname, './dist/js'), // 指定出口檔案的路徑目錄
        filename: 'bulid.js' // 制定出口檔案的名稱
        publicPath:'dist/'
        // path:所有輸出檔案的目標路徑;
        // publicPath:輸出解析檔案的目錄,url 相對於 HTML 頁面
    },
    module:{
        rules:[
        // 在webpack2中,loaders 被替換成了 rules 其實就是loader的規則
            //  實現 css 打包
            {
                test: /.css$/,
                use: [ 'style-loader', 'css-loader' ]
                // test 說明了當前 loader 能處理那些型別的檔案
                // use 則指定了 loader 的型別。
                // 注意:陣列中的loader不能省略擴充套件名
            },
            // 實現 scss 打包
            {
                test: /.scss$/,
                // 注意 是sass-loader ,不是 scss-loader
                use: [ 'style-loader', 'css-loader', 'sass-loader' ]
            },
            // 實現 less 打包
            {
                test: /.less$/,
                use: [ 'style-loader', 'css-loader', 'less-loader' ]
            },
            // 實現 url 資源打包
            {
                // 圖片和字型檔案使用 url-loader 來處理
                test: /.(png|jpg|gif|ttf|eot|woff|woff2|svg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        // options 為可以設定的選項
                        options: {
                            limit: 8192
                            // limit=8192表示將所有小於8kb的圖片都轉為base64形式(為什麼                               呢?因為一個很小的圖片,不值當的去傳送一個請求,減少請求次                               數。)
                            // (其實應該說超過8kb的才使用 url-loader 來對映到檔案,否                              則轉為dataurl形式)
                        }
                    }
              ]
               //保證輸出的圖片名稱與之前命名的圖片名稱保持一致(目前只是支援這樣的寫法,                   webpack3 沒有響應的options進行設定)
             // use:'url-loader?limit=8192&name=imgs/[name].[ext]' 
          }
          ]
      }
  }

在main.js中引入mui目錄中icons-extra.css的檔案

// 5、獲取less目錄中的less1.less檔案
require('../less/less1.less');
// 6、獲取src目錄中的mui目錄中icons-extra.css的檔案
require('../mui/css/icons-extra.css');

8、Webpack-dev-server結合後端伺服器的熱替換設定

webpack-dev-server提供了一個簡單的 web 伺服器,並且能夠實時重新載入(live reloading),同時把生成好的js和html構建到我們的電腦記憶體中,這樣的話,即使我們的目錄中沒有了相關js等檔案,還能夠載入出來,這樣能夠提高我們頁面執行速度。

安裝 webpack-dev-server 外掛

#先把之前依賴的包安裝
cnpm install
cnpm install webpack-dev-server --save-dev 
 // webpack.config.js
   const path = require('path');  // 首先要引入node.js中path 模組,用於處理檔案與目錄的路徑
   // const 命令宣告一個唯讀的常數,一旦宣告,值不可以改變,改變會報錯;只宣告不賦值也會報錯
   // 常數儲存的是一個不可以變化的變數。
   module.exports = {
       entry:'./src/./js/main.js', // 指定入口檔案
       output:{
           path: path.resolve(__dirname, 'dist/js'), // 指定出口檔案的路徑目錄
           filename: 'bulid.js' // 制定出口檔案的名稱
       },
       module:{
           rules:[
           // 在webpack2中,loaders 被替換成了 rules 其實就是loader的規則
               //  實現 css 打包
               {
                   test: /.css$/,
                   use: [ 'style-loader', 'css-loader' ]
                   // test 說明了當前 loader 能處理那些型別的檔案
                   // use 則指定了 loader 的型別。
                   // 注意:陣列中的loader不能省略擴充套件名
               },
               // 實現 scss 打包
               {
                   test: /.scss$/,
                   // 注意 是sass-loader ,不是 scss-loader
                   use: [ 'style-loader', 'css-loader', 'sass-loader' ]
               },
               // 實現 less 打包
               {
                   test: /.less$/,
                   use: [ 'style-loader', 'css-loader', 'less-loader' ]
               },
               // 實現 url 資源打包
               {
                   // 圖片檔案使用 url-loader 來處理
                   test: /.(png|jpg|gif|ttf)$/,
                   use: [
                   {
                       loader: 'url-loader',
                       // options 為可以設定的選項
                       options: {
                         limit: 8192
                         // limit=8192表示將所有小於8kb的圖片都轉為base64形式
                         // (其實應該說超過8kb的才使用 url-loader 來對映到檔案,否則轉為data url形式)
                     }
                 }
                 ]
             }
             ]
         },
          devServer: {
           // contentBase: './dist', // 在 localhost:8080(預設) 下建立服務,將 dist 目錄下的檔案,作為可存取檔案  contentBase:告訴伺服器從哪裡提供內容
           // 或者通過以下方式設定
           contentBase: path.join(__dirname, "dist"),
           compress: true,
           // 當它被設定為true的時候對所有的伺服器資源採用gzip壓縮
           // 對JS,CSS資源的壓縮率很高,可以極大得提高檔案傳輸的速率,從而提升web效能
           port: 9000, // 如果想要改埠,可以通過 port更改
           hot: true, // 啟用 webpack 的模組熱替換特性()
           inline: true, // 實現實時過載(實現自動重新整理功能)預設情況下是 true。
           host: "localhost" // 如果你希望伺服器外部可存取,指定使用一個 host。預設是 localhost(也就是你可以不寫這個host這個設定屬性)。
       }
    }
// package.json
   {
     "name": "mywebpack",
     "version": "1.0.0",
     "description": "",
     "main": "webpack.config.js",
     "scripts": {
       "test": "echo "Error: no test specified" && exit 1",
       "start": "webpack-dev-server --open"
       // "start": "webpack-dev-server --open --port 8080 --hot --inline"  // 如果在這裡設定了,就不用在webpack.config.js中設定devServer屬性了。
     },
     "author": "",
     "license": "ISC",
     "devDependencies": {
       "css-loader": "^0.28.7",
       "file-loader": "^1.1.5",
       "html-webpack-plugin": "^2.30.1",
       "less": "^3.0.0-alpha.3",
       "less-loader": "^4.0.5",
       "node-sass": "^4.5.3",
       "sass-loader": "^6.0.6",
       "style-loader": "^0.19.0",
       "url-loader": "^0.6.2",
       "webpack": "^3.8.1",
       "webpack-dev-server": "^2.9.3"
     }
   }
   ```
-   在命令列中執行 `npm start`,就會看到瀏覽器自動載入頁面。如果現在修改和儲存任意原始檔,web 伺服器就會自動重新載入編譯後的程式碼,但是開啟後發現,開啟的是 dist目錄,我們想要的是 index.html顯示我們的頁面,所以這是我們還要藉助裡另一個 `html-webpack-plugin` 外掛。

html-webpack-plugin 簡單建立 HTML 檔案,用於伺服器存取,其中包括使用script標籤的body中的所有webpack包。

安裝 html-webpack-plugin 外掛

cnpm install --save-dev html-webpack-plugin

webpack.config.js設定

const path = require('path'); // 首先要引入node.js中path 模組,用於處理檔案與目錄的路徑
// const 命令宣告一個唯讀的常數,一旦宣告,值不可以改變,改變會報錯;只宣告不賦值也會報錯
// 常數儲存的是一個不可以變化的變數。
// 引入html-webpack-plugin 外掛
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
    entry: './src/./js/main.js', // 指定入口檔案
    output: {
        path: path.resolve(__dirname, 'dist/js'), // 指定出口檔案的路徑目錄
        filename: 'bulid.js' // 制定出口檔案的名稱
    },
    module: {
        rules: [
            // 在webpack2中,loaders 被替換成了 rules 其實就是loader的規則
            //  實現 css 打包
            {
                test: /.css$/,
                use: ['style-loader', 'css-loader']
                    // test 說明了當前 loader 能處理那些型別的檔案
                    // use 則指定了 loader 的型別。
                    // 注意:陣列中的loader不能省略擴充套件名
            },
            // 實現 scss 打包
            {
                test: /.scss$/,
                // 注意 是sass-loader ,不是 scss-loader
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
            // 實現 less 打包
            {
                test: /.less$/,
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            // 實現 url 資源打包
            {
                // 圖片檔案使用 url-loader 來處理
                test: /.(png|jpg|gif|ttf)$/,
                use: [{
                    loader: 'url-loader',
                    // options 為可以設定的選項
                    options: {
                        limit: 8192
                            // limit=8192表示將所有小於8kb的圖片都轉為base64形式
                            // (其實應該說超過8kb的才使用 url-loader 來對映到檔案,否則轉為data url形式)
                    }
                }]
            }
        ]
    },
    devServer: {
        // contentBase: './dist', // 在 localhost:8080(預設) 下建立服務,將 dist 目錄下的檔案,作為可存取檔案  contentBase:告訴伺服器從哪裡提供內容
        // 或者通過以下方式設定
        contentBase: path.join(__dirname, "dist"),
        port: 9000, // 如果想要改埠,可以通過 port更改
        hot: true, // 啟用 webpack 的模組熱替換特性()
        inline: true, // 實現實時過載(實現自動重新整理功能)預設情況下是 true。
        host: "localhost" // 如果你希望伺服器外部可存取,指定使用一個 host。預設是 localhost(也就是你可以不寫這個host這個設定屬性)。
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: '首頁', // 用於生成的HTML檔案的標題
            filename: 'index.html', //寫入HTML的檔案。預設為index.html。也可以指定一個子目錄(例如:)assets/admin.html
            template: 'index.html' // Webpack需要模板的路徑
        }),
        new webpack.HotModuleReplacementPlugin() // 需要結合 啟用熱替換模組(Hot Module Replacement),也被稱為 HMR
    ]
}

再次使用npm start命令就可以實現瀏覽器自動更新。

問題來了,HtmlWebpackPlugin中的 title並沒有顯示出來,原因是需要在定義的template模板中使用ejs語法,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <!-- EJS 語法 
            /* EJS是一個簡單高效的模板語言,通過資料和模板,可以生成HTML標記文字。可以說EJS是一個JavaScript庫,EJS可以同時執行在使用者端和伺服器端,使用者端安裝直接引入檔案即可 */
        -->
    <title><%= htmlWebpackPlugin.options.title%></title>
</head>
<body>
    <input type="text" id="first">
    <input type="button" id="btn" value="+">
    <input type="text" id="two">
    <input type="button" id="btn" value="=">
    <input type="text" id="res">
    <div id="bg1"></div>
    <div id="bg2"></div>
</body>
</html>

再次使用npm start命令就可以啦。

9、ES6轉換為ES5語法

安裝

cnpm install --save-dev babel-loader babel-core babel-preset-env

babel-core如果某些程式碼需要呼叫Babel的API進行轉碼,就要使用babel-core模組

babel-preset-env通過根據您的目標瀏覽器或執行時環境自動確定您需要的Babel外掛

babel 對一些公共方法使用了非常小的輔助程式碼,比如 _extend。 預設情況下會被新增到每一個需要它的檔案中,你可以引入 babel runtime 作為一個獨立模組,來避免重複引入。

你必須執行 npm install babel-plugin-transform-runtime --save-dev 來把它包含到你的專案中

也要使用 npm install babel-runtime --save 把 babel-runtime 安裝為一個依賴

設定

// 實現 url 資源打包
                    {
                        // 圖片檔案使用 url-loader 來處理
                        test: /.(png|jpg|gif|ttf)$/,
                        use: [{
                            loader: 'url-loader',
                            // options 為可以設定的選項
                            options: {
                                limit: 8192
                                    // limit=8192表示將所有小於8kb的圖片都轉為base64形式
                                    // (其實應該說超過8kb的才使用 url-loader 來對映到檔案,否則轉為data url形式)
                            }
                        }]
                    },
                    // 實現 ES6轉 ES5
                    {
                        test: /.js$/,
                        exclude: /(node_modules)/,  // exclude 排除的意思,把 node_modules資料夾排除編譯之外
                        use: {
                            loader: 'babel-loader',
                            options: {
                            // presets 預設列表(一組外掛)載入和使用
                            presets: ['env'],
                            plugins: ['transform-runtime'] // 載入和使用的外掛列表
                            }
                        }
                    }

把一些程式碼改成ES6 語法的寫法

-   ```js
    // main.js
    // 1、獲取index.html中的dom物件
    var first = document.getElementById('first');
    var btn1 = document.getElementById('btn1');
    var two = document.getElementById('two');
    var res = document.getElementById('res');
    console.log(1);
    btn1.onclick = function() {
        var firstValue = parseFloat(first.value);
        var twoValue = parseFloat(two.value);
        //2、獲取 module1.js中的 sum函數
        //http://www.ruanyifeng.com/blog/2015/05/require.html
        console.log(2);
        /* var sum = require('./module1.js');
         res.value = sum(firstValue,twoValue);*/
        res.value = sumObj.sum(firstValue, twoValue);
    }
    // 3、獲取css目錄中的main.css檔案
    // require('../css/main.css');
    //  把步驟3 改為 ES6寫法,引入css目錄中的main.css檔案
    import '../css/main.css';
    // 4、獲取sass目錄中的scss1.scss檔案
    require('../sass/scss1.scss');
    // 5、獲取less目錄中的less1.less檔案
    require('../less/less1.less');
    // 6、獲取src目錄中的mui目錄中icons-extra.css的檔案
    require('../mui/css/icons-extra.css');
    // 把 var sum = require('./module1.js'); 寫成 ES6語法
    import sumObj from './module1.js'
    ```
// moudule1.js
function sum(x,y){
    return x + y;
}
// 匯出 sum 函數
// module.exports = sum;
    // 改成ES6 的寫法語法
export default{
    sum
}

10、防止檔案快取(生成帶有20位的hash值的唯一檔案)

// webpack.config.js
output: {
        path: path.resolve(__dirname, 'dist/js'), // 指定出口檔案的路徑目錄
        // filename: 'bulid.js' // 制定出口檔案的名稱
        filename: '[name].[hash].js' // 將入口檔案重新命名為帶有20位的hash值的唯一檔案
    }

11、抽取CSS為單獨檔案

安裝外掛從 build.js檔案中提取文字(CSS)到單獨的檔案

npm install --save-dev extract-text-webpack-plugin

在webpack.config.js中設定

const path = require('path'); // 首先要引入node.js中path 模組,用於處理檔案與目錄的路徑
// const 命令宣告一個唯讀的常數,一旦宣告,值不可以改變,改變會報錯;只宣告不賦值也會報錯
// 常數儲存的是一個不可以變化的變數。
// 引入html-webpack-plugin 外掛
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
    entry: './src/./js/main.js', // 指定入口檔案
    output: {
        path: path.resolve(__dirname, 'dist'), // 指定出口檔案的路徑目錄
        // filename: 'bulid.js' // 制定出口檔案的名稱
        // path指定了本地構建地址,publicPath指定在瀏覽器中所參照的,指定的是構建後在html裡的路徑
        // publicPath: './',
        // 將入口檔案重新命名為帶有20位的hash值的唯一檔案
        filename: '[name].[hash].js' 
    },
    module: {
        rules: [
            // 在webpack2中,loaders 被替換成了 rules 其實就是loader的規則
            //  實現 css 打包
            /*{
                test: /.css$/,
                use: ['style-loader', 'css-loader']
                    // test 說明了當前 loader 能處理那些型別的檔案
                    // use 則指定了 loader 的型別。
                    // 注意:陣列中的loader不能省略擴充套件名
            },*/
            // 實現 scss 打包
            {
                test: /.scss$/,
                // 注意 是sass-loader ,不是 scss-loader
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
            // 實現 less 打包
            {
                test: /.less$/,
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            // 實現 url 資源打包
            {
                // 圖片檔案使用 url-loader 來處理
                test: /.(png|jpg|gif|ttf)$/,
                use: [{
                    loader: 'url-loader',
                    // options 為可以設定的選項
                    options: {
                        limit: 8192
                            // limit=8192表示將所有小於8kb的圖片都轉為base64形式
                            // (其實應該說超過8kb的才使用 url-loader 來對映到檔案,否則轉為data url形式)
                    }
                }]
               //保證輸出的圖片名稱與之前命名的圖片名稱保持一致(目前只是支援這樣的寫法,                   webpack3 沒有響應的options進行設定)
                // use:'url-loader?limit=8192&name=imgs/[name].[ext]' 
            },
            // 實現 ES6轉 ES5
            {
                test: /.js$/,
                exclude: /(node_modules)/, // exclude 排除的意思,把 node_modules資料夾排除編譯之外
                use: {
                    loader: 'babel-loader',
                    options: {
                        // presets 預設列表(一組外掛)載入和使用
                        presets: ['env'],
                        plugins: ['transform-runtime'] // 載入和使用的外掛列表
                    }
                }
            },
            // 提取 css模組(如果使用這個模組的話,需要把之前的CSS打包模組註釋掉,不然會重複)
            {
                test: /.css$/,
                use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use: "css-loader"
                })
            }
        ]
    },
    devServer: {
        // contentBase: './dist', // 在 localhost:8080(預設) 下建立服務,將 dist 目錄下的檔案,作為可存取檔案  contentBase:告訴伺服器從哪裡提供內容
        // 或者通過以下方式設定
        contentBase: path.join(__dirname, "dist"),
        port: 9000, // 如果想要改埠,可以通過 port更改
        hot: true, // 啟用 webpack 的模組熱替換特性()
        inline: true, // 實現實時過載(實現自動重新整理功能)預設情況下是 true。
        host: "localhost" // 如果你希望伺服器外部可存取,指定使用一個 host。預設是 localhost(也就是你可以不寫這個host這個設定屬性)。
    },
    plugins: [
        // 從 bundle 中提取文字(CSS)到單獨的檔案      
        new ExtractTextPlugin({
            //  提取css,並重名為帶有 20位的hash值的唯一檔案
            filename: '[name].[hash].css',
            // 將所有的獨立檔案模組(這裡指的是css檔案)合併成一個檔案
            allChunks: true
        }),
        new HtmlWebpackPlugin({
            title: '首頁', // 用於生成的HTML檔案的標題
            filename: 'index.html', //寫入HTML的檔案。預設為index.html。也可以指定一個子目錄(例如:)assets/admin.html
            template: 'index.html' // Webpack需要模板的路徑
                // template: 'index.ejs' // Webpack需要模板的路徑
        }),
        // 需要結合webpack-dev-server 啟用熱替換模組(Hot Module Replacement),也被稱為 HMR
        new webpack.HotModuleReplacementPlugin()
    ]
}

12、開發環境和生產環境的分離

(1)開發環境與生產環境分離的原因如下:

  • 在開發環境中,我們使用熱更新外掛幫助我們實現瀏覽器的自動更新功能,我們的程式碼沒有進行壓縮,如果壓縮了不方便我們偵錯程式碼等等,所以以上這些程式碼不應出現在生產環境中。
  • 生產環境中,我們把專案部署到伺服器時,我們會對程式碼進行各種各樣的優化,比如壓縮程式碼等等,這時候我們不應該把這些程式碼放到開發環境中,不利於程式碼開發和偵錯。

總結:針對以上這些說明,我們很有必要把區分開發環境與生產環境分離。

(2)開發環境的設定和生產換環境設定的區別。

  • 開發環境有的設定,生產環境不一定有,比如說熱更新時使用到的HotModuleReplacementPlugin。
  • 生產環境有的設定,開發環境不一定有,比如說用來壓縮js用的UglifyJsPlugin。

如何去做?

1> 因為webpack 預設找的是 webpack.config.js組態檔,所以要把開發環境的webpack.config.js組態檔改為webpack.dev.config.js代表開發環境的組態檔。

2> 新建一個webpack.prod.config.js,再把開發環境中的webpack.config.js複製進去(沒用的組態檔該刪除的刪除

3> 修改package.json檔案(在scripts 標籤中新增"dev"和"prod" 屬性設定)

 "scripts": {
        "test": "echo "Error: no test specified" && exit 1",
        "dev": "webpack --config webpack.dev.config.js",
        "prod": "webpack --config webpack.prod.config.js"
    },

怎樣執行命令

執行開發環境的中設定

npm run dev

執行生產環境的中設定

npm run prod

13、在生產環境中設定程式碼壓縮功能

設定webpack.prod.config.js 檔案

// webpack.prod.config.js
var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
 // ……
   plugins: [
       // ……
        // js程式碼 壓縮
        new UglifyJsPlugin({
            compress: {
                warnings: false
            }
        })
    ]

執行 npm run prod 命令

四、webpack1和webpack2的區別

webpack1.0已經廢棄使用,建議使用webpack2.0+

1、resolve.modulesDirectories 被重新命名為 resolve.modules

2、module.loaders 將繼續支援,但在未來它將被module.rules 替換。

以上就是webpack安裝設定及使用教學詳解的詳細內容,更多關於webpack安裝設定教學的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com