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后的报错信息与报错文件,不受打包后的干扰,准确定位报错源文件及源文件的报错行。
    在这里插入图片描述
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/jw2268136570/article/details/104900182