webpack 開發環境優化 【實踐】

上一篇博客:開發環境打包

實踐結果

package.json

{
  "name": "webpack_dev_test_better",
  "version": "1.0.0",
  "devDependencies": {
    "css-loader": "^3.4.2",
    "file-loader": "^5.1.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "style-loader": "^1.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.42.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3"
  }
}

entry.js(js模塊熱替換的代碼示例)

import {status} from  './test.js'
console.log('status:'+status);
if (module.hot) {
    // test.js模塊熱更新開啓,替換後觸發回調(其它模塊不會重新打包構建)。
    module.hot.accept('./test.js', function() {
        console.log('js HMR success');
        console.log('status:'+status);
    });
}

webpack.config.js

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry:["./src/js/entry.js","./src/index.html"],
    output:{
        path:resolve(__dirname,'build'),
        filename:'js/built.js'
    },
    module:{
        rules:[
            {
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            },
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            },
            {
                test: /\.(jpg|png|gif)$/,
                loader: 'url-loader',
                options: {
                    limit: 8 * 1024,
                    name: '[hash:10].[ext]',
                    esModule:false,
                    outputPath: 'images'
                }
            },
            {
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
                exclude: /\.(html|js|css|less|jpg|png|gif)/,
                loader: 'file-loader',
                options: {
                    name: '[hash:10].[ext]',
                    outputPath: 'media'
                }
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:'./src/index.html'
        })
    ],
    mode:'development',
    devServer: {
        contentBase: resolve(__dirname, 'build'),// 項目構建後路徑
        compress: true,// 啓動gzip壓縮
        port: 3000,// 端口號
        open: true,// 自動打開瀏覽器
        hot: true  // 啓動模塊熱替換HMR
    },
    // 開發環境優選:'eval-source-map',生產環境視情況而定(源代碼是否要隱藏?調試是否要更友好?)。
    // eval:內聯source-map,速度最快。source-map:定位源代碼報錯位置,調試最優。
    devtool: 'eval-source-map'
};

實踐準備

開發環境打包【未優化】

創建項目:webpack_dev_test_better
初始化
npm init
npm i webpack webpack-cli -D
// 上篇博客編譯打包功能涉及到的所有依賴
npm i css-loader file-loader html-loader html-webpack-plugin less less-loader style-loader url-loader -D
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry:"./src/js/entry.js",
    output:{
        path:resolve(__dirname,'build'),
        filename:'js/built.js'
    },
    module:{
        rules:[
            {
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            },
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            },
            {
                test: /\.(jpg|png|gif)$/,
                loader: 'url-loader',
                options: {
                    limit: 8 * 1024,
                    name: '[hash:10].[ext]',
                    esModule:false,
                    outputPath: 'images'
                }
            },
            {
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
                exclude: /\.(html|js|css|less|jpg|png|gif)/,
                loader: 'file-loader',
                options: {
                    name: '[hash:10].[ext]',
                    outputPath: 'media'
                }
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:'./src/index.html'
        })
    ],
    mode:'development'
};

實踐過程

一:自動構建(devServer)【代碼修改後】

1.解決問題
  • 任意一個模塊發生變化,都需要再次手動執行 打包、刷新瀏覽器 等重複步驟。
2.解決方案
  • webpack配置devServer(熱部署)

注意:熱部署功能並不能監聽webpack.config.js文件,當修改了webpack配置,新配置要想生效,必須重啓webpack服務。

3.操作示例
  • 下載devServer
npm i webpack-dev-server -D
  • 配置devServer:webpack.config.js
module.exports = {
...,
mode:'devlopment',
devServer: {
      contentBase: resolve(__dirname, 'build'),// 項目構建後路徑
      compress: true,// 啓動gzip壓縮
      port: 3000,// 端口號
      open: true// 自動打開瀏覽器
  }
}
  • 啓動devServer
// 內存中編譯打包,不會有build輸出
npx webpack-dev-server

在這裏插入圖片描述

  • 啓動結果:
    • 自動編譯打包,並未輸出build文件夾。
    • 自動啓動默認瀏覽器並訪問http://localhost:3000/,呈現與瀏覽器打開build/index.html一致。
    • 代碼修改後,瀏覽器自動刷新,並呈現修改後的代碼邏輯。

二:加快構建(HMR)【代碼修改後】

1.解決問題
  • devServer普通配置啓動後,一個模塊發生變化,所有模塊都要重新打包,構建速度慢。
2.解決方案
  • 啓動devServer的HMR功能(hot module replacement 模塊熱替換)。
    作用:一個模塊發生變化,只會重新打包這一個模塊,極大提速構建速度。
3.操作示例

不同模塊類型對HMR功能的支持情況不同,下面實踐測試不同類型模塊的支持情況及其配置。

  • 樣式文件:配置後可以使用HMR功能(開發環境下使用的style-loader內部實現了)。
module.exports = {
entry:["./src/js/entry.js","./src/index.html"],
...,
mode:'devlopment',
devServer: {
      contentBase: resolve(__dirname, 'build'),
      compress: true,
      port: 3000,
      open: true,
      // 實踐證明:
      // 1.配置後,樣式類型模塊成功HMR.
      // 2.但會讓html文件熱部署失效,需把index.html配置爲entry)
      hot: true  // 啓動模塊熱替換HMR。
  }
}

在這裏插入圖片描述

  • js文件:默認不能使用HMR功能。需要在需要支持HMR功能的js文件(不能是入口文件)中添加支持HMR功能的代碼。
    • 證明:默認不支持HMR
      在這裏插入圖片描述
    • 證明:在src/js/entry.js中添加代碼後支持src/js/test.js文件的HMR
// entrt.js
import {status} from  './test.js'
console.log('status:'+status);
//let status2 = 1;
// 實驗證明1:下段代碼放在test.js中不能觸發HMR。
if (module.hot) {
    // test.js模塊熱更新開啓,替換後觸發回調(其它模塊不會重新打包構建)。
    module.hot.accept('./test.js', function() {
        console.log('js HMR success');
        console.log('status:'+status);
    });
// 實驗證明2:入口文件entry.js不能支持HMR。
    //module.hot.accept('./entry.js', function() {
    //    console.log('js HMR success');
    //    console.log('status:'+status2);
    //});
}

在這裏插入圖片描述

  • html文件:默認不能也不需要HMR功能。

三:方便調試(source-map)【代碼報錯後】

1.解決問題
  • 打包前後代碼千差萬別,打包後代碼出錯很難定位到打包前代碼的出錯位置,不方便調試。
2.解決方案
  • 配置devtool:所有可選配置項爲 [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
3.操作示例

-1.報錯源文件:src/js/test.js

export let status = 6;
status.fnTest();
  • 2.不使用source-map時的報錯信息與報錯文件,受到打包後的干擾。
    在這裏插入圖片描述
    在這裏插入圖片描述
  • 3.配置source-map
module.exports = {
...,
// 開發環境優選:'eval-source-map',生產環境視情況而定(源代碼是否要隱藏?調試是否要更友好?)。
// eval:內聯source-map,速度最快。source-map:定位源代碼報錯位置,調試最優。
devtool: 'eval-source-map'
}
  • 4.使用source-map後的報錯信息與報錯文件,不受打包後的干擾,準確定位報錯源文件及源文件的報錯行。
    在這裏插入圖片描述
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章