webpack打包模式

打包模式

打包模式 是为了告知 webpack 使用相应模式的内置优化。

模式分类

模式名称模式名字特点场景
开发模式development调试代码,实时加载,模块热替换等本地开发
生产模式production压缩代码,资源优化,更轻量等打包上线

设置方式

方式1: 在webpack.config.js配置文件设置mode选项

module.exports = {
    // 打包模式 (development 开发模式-使用相关内置优化)
    mode:'development',
   }

方式2: 在package.json命令行设置mode参数

 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --mode=production",     // 生产模式
    "dev": "webpack serve --open --mode=development"    // 开发模式
  },

注意:命令行设置的优先级高于配置文件中的

打包模式的应用

需求
在开发模式下:使用 style-loader 内嵌 css 代码在 js 中,让热替换更快
载生产模式下:提取 css 代码,让浏览器缓存和并行下载 js 和 css 文件

步骤

  1. 下载 cross-env 软件包到当前项目中
    命令:npm i cross-env --save-dev
  2. 配置自定义命令,传入参数名和值到 process.env 对象上( process.env是 Node.js 环境变量)
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "cross-env NODE_ENV=production webpack --mode=production",
    "dev": "cross-env NODE_ENV=development webpack serve --open --mode=development"
  },

注意:NODE_ENV=production 和 webpack打包时的–mode=production 是没有关系的,二者互不影响

  1. 在 webpack.config.js 调用使用做判断区分
// 打包css代码
{
   test: /\.css$/i,
   use: [process.env.NODE_ENV ==='development' ? 'style-loader': MiniCssExtractPlugin.loader, 'css-loader'],
 },

需求
前端项目中,在开发模式下打印语句生效,在生产模式下打印语句失效
问题: cross-env 设置的只在 Node.js 环境生效,前端代码无法访问 process.env.NODE_ENV
解决方法: 使用Webpack内置的DefinePlugin插件
作用: 在编译时,将前端代码中匹配的变量名,替换为值或表达式

步骤

  1. 在webpack 中配置 DefinePlugin 插件
const webpack = require('webpack')
module.exports = {
plugins: [
        new webpack.DefinePlugin({
        	// key是注入到打包后的前端JS代码中作为全局变量
			// value是变量对应的值(在corss-env 注入在 node.js 中的环境变量字符串)
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
        })
    ],
}
  1. 在前端代码中使用,并在两个模式下观察区别
if(process.env.NODE_ENV === 'production'){
    console.log = function(){}
}
console.log('开发模式下生效, 生产模式下失效')

开发环境调错 —source map

问题: 代码被压缩和混淆,无法正确定位源代码位置(行数和列数)
source map: 可以准确追踪error和warning在原始代码的位置
设置: 在webpack.config.js配置devtool选项
inline-source-map选项:把源码的位置信息一起打包在js 文件内

const config = {
    // 其他代码...
};

// 开发环境下使用source map选项
if(process.env.NODE_ENV === 'development'){
    config.devtool = 'inline-source-map'
}

module.exports = config

注意: source map仅适用于开发环境,不要在生产环境使用(防止被轻易查看源码位置)

解析别名alias

解析别名: 路径解析别名设置,让前端代码引入路径更简单(而且使用绝度路径)
解决: 在webpack.config.js 中配置解析别名来代表 src 绝对路径

const config = {
	// 解析别名
    resolve: {
        alias: {
            // __dirname 会动态获取当前文件所在文件夹的绝对路径
            // @ 表示 src 文件夹
            '@': path.resolve(__dirname, 'src')
        }
    }
 }

在前端代码中引入路径

import yourAxios from '@/utils/request.js'
console.log(yourAxios)

优化-CDN使用

CDN定义: 内容分发网络,指的是一组分布在各个地区的服务器
作用: 把静态资源文件/第三方库放在CDN网络中各个服务器中,供用户就近请求获取
好处: 减轻自己服务器请求压力,就近请求物理延迟低,配套缓存策略

需求: 开发模式使用本地第三方库,生产模式下使用CDN加载引入

步骤:

  1. 在 html 中引入第三方库的 CDN 地址并用模板语法判断
 <% if(htmlWebpackPlugin.options.useCdn){ %>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
 <% } %>
 
 <% if(htmlWebpackPlugin.options.useCdn){ %>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.js"></script>
  <% } %>
  1. 配置 webpack.config.js 中 externals 外部扩展选项(防止某些 import 的包被打包)
// 生产环境下使用相关配置
if (process.env.NODE_ENV === 'production') {
    // 外部扩展(让 webpack 防止 import 的包被打包进来)
    config.externals = {
      // key:import from 语句后面的字符串
      // value:留在原地的全局变量(最好和 cdn 在全局暴露的变量一致)
      'bootstrap/dist/css/bootstrap.min.css': 'bootstrap',
      'axios': 'axios',
    }
  }
const config = {
	// 插件(给Webpack提供更多功能)
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'public/login.html'),   // 模版文件
            filename: path.resolve(__dirname, 'dist/login/index.html'),  // 输出文件
            useCdn: process.env.NODE_ENV === 'production'
        }),
 }

多页面打包

  1. 准备源码(html,css,js)放入相应位置,并改用模块化语法导出
  2. 配置 webpack.config.js 多入口和多页面的设置
const config = {
    // 入口
    entry: {
        'login': path.resolve(__dirname, 'src/login/index.js'),
        'content': path.resolve(__dirname, 'src/content/index.js'),
    },
    // 出口
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: './[name]/index.js',
        clean: true  //生成打包后内容之前,清空输出目录
    },
    // 插件(给Webpack提供更多功能)
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'public/login.html'),   // 模版文件
            filename: path.resolve(__dirname, 'dist/login/index.html'),  // 输出文件
            useCdn: process.env.NODE_ENV === 'production',   // 生产模式下使用 cdn 引入的地址
            chunks: ['login']   // 引入哪些打包后的模块(和 entry 中的 key 一致)
        }),
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, 'public/content.html'),   // 模版文件
            filename: path.resolve(__dirname, 'dist/content/index.html'),  // 输出文件
            useCdn: process.env.NODE_ENV === 'production',   // 生产模式下使用 cdn 引入的地址
            chunks: ['content']   // 引入哪些打包后的模块(和 entry 中的 key 一致)
        }),
        new MiniCssExtractPlugin({
            filename: './[name]/index.css'
        }),   // 生成css文件
    ]
 }

优化-分割公共代码

需求: 把2个以上页面引用的公共代码提取

步骤:

  1. 配置webpack.config.js的splitChunks分割功能
const config = {
	optimization: {
        // 代码分割
        splitChunks: {
            chunks: 'all', // 所有模块动态非动态移入的都分割分析
            cacheGroups: { // 分隔组
                commons: { // 抽取公共模块
                    minSize: 0, // 抽取的chunk最小大小字节
                    minChunks: 2, // 最小引用数
                    reuseExistingChunk: true, // 当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用
                    name(module, chunks, cacheGroupKey) { // 分离出模块文件名
                        const allChunksNames = chunks.map((item) => item.name).join('~') // 模块名1~模块名2
                        return `./js/${allChunksNames}` // 输出到 dist 目录下位置
                    }
                }
            }
        }
    },
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值