• Webpack


    本节目标

    • 基础配置

    基础配置

    webpack是一个JS的静态打包工具

    静态模块: 编写代码过程中的, html, css, js, 图片等固定内容的文件

    打包: 把静态模块的内容, 压缩, 整合, 转译等 (前端工程化)

    转译: 把less/sass转成css代码, 把ESC6+ 降级成ES5, 支持多种模块标准语法

    体验

    1. 新建并初始化项目, 编写业务源代码

    npm init -y

    1. 下载webpack webpack-cli 到当前目录中(版本独立), 并配置局部自定义命令

    npm i webpack webpack-cli --save-dev

    1. 运行打包命令, 自动产生dist分发文件夹(压缩和优化后, 用于最终运行的代码)

    npm run build

    1. 执行过程

    入口和出口

    通过webpack配置, 影响打包的过程和结果

    步骤

    1. 官网: 概念 | webpack 中文文档 | webpack中文文档 | webpack中文网
    2. 项目根目录, 新建webpack.config.js配置文件
    3. 导出配置对象, 配置入口/出口文件的路径
    4. 只有和入口产生直接/间接的引入关系, 才会被打包
    1. const path = require('path');
    2. module.exports = {
    3. // 自定入口文件
    4. entry: path.resolve(__dirname, 'src/login/index.js'),
    5. // 自定输出文件
    6. output: {
    7. // 文件位置
    8. path: path.resolve(__dirname, 'dist'),
    9. // 文件名称
    10. filename: './login/inde.js',
    11. },
    12. };

    手动引入HTML

    需求 : 点击登录按钮, 判断手机号和验证码程度

    步骤

    1. 准备登录页面(index.html)
    2. 编写核心JS逻辑代码(index.js), 打包
    3. 手动复制网页到dist中,
    4. 在页面中引入打包后的js, 运行

    自动生成HTML

    HtmlWebpackPlugin简化了HTML文件的创建, 以便为你的webpack包提供服务

    步骤

    1. 位置: 官网搜索HtmlWebpackPlugin
    2. 安装: npm install --save-dev html-webpack-plugin
    3. 配置
    1. const path = require('path');
    2. const HtmlWebpackPlugin = require('html-webpack-plugin');
    3. module.exports = {
    4. ......
    5. // 注册插件
    6. plugins: [new HtmlWebpackPlugin({
    7. // 插件配置
    8. template: path.resolve(__dirname, 'public/login.html'), // 模板文件
    9. filename: path.resolve(__dirname, 'dist/login.html'), // 输出文件
    10. })],
    11. };

    打包css代码

    webpack默认只识别js代码, 通过配置loader加载器进行解析

    使用

    1. 位置: 官网搜索css-loader
    2. css-loader( 解析css ) 和 style-loader( 把解析后的css插入到DOM ) 配合使用
    3. 安装 npm install css-loader style-loader --save-dev
    4. 引入css文件到src/login/index.js中
    5. 配置webpack.config.js 让其拥有该加载器的功能
    1. module.exports = {
    2. ... ...
    3. // 配置加载器
    4. module: {
    5. rules: [
    6. {
    7. test: /\.css$/i,
    8. use: ['style-loader', 'css-loader'],
    9. },
    10. ],
    11. },
    12. };
    1. 安装 npm i bootstrap
    2. 引入 import 'bootstrap/dist/css/bootstrap.min.css'

    提取css代码

    把css代码提出成单独文件, 可以减少js文件体积, 并且css文件可以被浏览器缓存

    步骤

    1. 位置: 官网搜索MiniCssExtractPlugin
    2. 使用mini-css-extract-plugin插件提取css
    3. 下载命令: npm install --save-dev mini-css-extract-plugin
    4. 配置文件: 在webpack.config.js中, 配置使用
    1. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    2. module.exports = {
    3. plugins: [new MiniCssExtractPlugin()],
    4. module: {
    5. rules: [
    6. {
    7. test: /\.css$/i,
    8. // css与js一体打包
    9. // use: ['style-loader', 'css-loader'], // 被注释的加载器
    10. // 提取css插件
    11. use: [MiniCssExtractPlugin.loader, "css-loader"],
    12. },
    13. ],
    14. },
    15. };
    1. 注意: 该插件不能和style-loader一起使用

    压缩css代码

    css代码提取后没有被压缩, 通过css-minimizer-webpack-pligin插件, 压缩自己的css文件

    步骤

    1. 位置: 官网搜索CssMinimizerWebpackPlugin
    2. 安装: npm install css-minimizer-webpack-plugin --save-dev
    3. 配置
    1. const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
    2. module.exports = {
    3. ... ...
    4. // 优化配置
    5. optimization: {
    6. // 最小化
    7. minimizer: [
    8. // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
    9. // 保证js代码还能压缩
    10. `...`,
    11. new CssMinimizerPlugin(),
    12. ],
    13. },
    14. };

    打包less代码

    使用less-loder加载器, 把less代码转译为css代码

    步骤

    1. 位置: 官网搜索less-loader
    2. 新建 index.less代码文件, 设置背景图, 引入代码文件
    3. 下载: npm install less less-loader --save-dev
    4. 注意 less-loader 需要配置less软件包使用
    5. 配置
    1. module.exports = {
    2. module: {
    3. rules: [
    4. // 提取css的配置
    5. ... ...
    6. // less打包配置
    7. {
    8. test: /\.less$/i,
    9. use: [
    10. // compiles Less to CSS
    11. // MiniCssExtractPlugin.loader 与 style-loader 只能用一个
    12. // 'style-loader',
    13. MiniCssExtractPlugin.loader,
    14. 'css-loader',
    15. 'less-loader',
    16. ],
    17. },
    18. ],
    19. },
    20. };

    打包图片

    webpack5内置资源模块(字体,图片等)打包模块, 无需额外的loader, 只需要一些配置即可

    1. module.exports = {
    2. // 配置加载器(识别更多模块文件的内容)
    3. module: {
    4. rules: [
    5. // 提取css的配置
    6. ... ...
    7. // less打包配置
    8. ... ...
    9. // 图片文件打包配置
    10. {
    11. test: /\.(png|svg|jpg|jpeg|gif)$/i,
    12. type: 'asset',
    13. generator: {
    14. // 输出位置
    15. filename: 'assets/[hash][ext][query]',
    16. },
    17. }
    18. ],
    19. },
    20. ... ...
    21. };
    1. /**
    2. * JS中
    3. * 引入本地图片资源 要用import方法
    4. * 如果是网络图片, 可以使用字符串网址
    5. */
    6. import logo from './assets/logo.png'
    7. const thenImg = document.createElement('img')
    8. thenImg.src = logo
    9. document.querySelector('.login-wrap').appendChild(thenImg)

    配置解释

    1. 位置: 官网搜索 '资源模块'
    2. test: 配置文件类型( 根据后缀名匹配文件 )
    3. type: 配置打包类型( asset表示自动适配 )
    • 自动适配的依据是文件大小, 判断临界默认值为8kb
    • 大于8kb的文件: 发送一个单独的文件并导出URL地址( 拷贝图片 )
    • 小于8kb的文件: 导出一个data URL(base64字符串)
    1. filename: 配置打包的出口( 打包后文件存放位置 )
    • 占位符 [hash] 对模块内容做算法计算, 得到映射的数字字母组合的字符串( 生成文件名 )
    • 占位符 [ext] 使用当前模块原本的占位符, 例如 .png .jpg等字符串 ( 沿用文件后缀 )
    • 占位符 [query] 保留引入文件时代码中查询参数( 只有URL下有效 ) ( 不太常用 )

    登录页

    完成登录页的核心流程, 以及Alert警告框的使用

    流程

    步骤

    1. 下载使用axios (npm i axios)
    2. 准备并修改utils工具包下的文件 (导出函数)
    3. 编写逻辑代码, 打包后运行

    代码

    1. /**
    2. * 完成登录功能
    3. * 1,下载axios
    4. * 2,修改utils下的文件, 导出函数
    5. * 3,完成登录, 打包运行
    6. */
    7. import axios from '../utils/request'
    8. import { myAlert } from '../utils/alert'
    9. document.querySelector('.btn').addEventListener('click', function () {
    10. const p = document.querySelector('.login-form [name=mobile]').value
    11. const c = document.querySelector('.login-form [name=code]').value
    12. if (!phone(p)) {
    13. // alert('手机号不正确')
    14. myAlert(false, '手机号不正确')
    15. return
    16. }
    17. if (!code(c)) {
    18. // alert('验证码不正确')
    19. myAlert(false, '验证码不正确')
    20. return
    21. }
    22. axios({
    23. url: '/v1_0/authorizations',
    24. method: 'POST',
    25. data: {
    26. mobile: p,
    27. code: c
    28. }
    29. }).then(() => {
    30. myAlert(true, '登录成功')
    31. }, (error) => {
    32. myAlert(false, error.response.data.message)
    33. })
    34. })

    开发环境

    通过webpack-dev-server插件, 实现代码热更新

    介绍

    • 作用 启动Web服务器, 自动检测代码变化, 热更新到网页
    • 注意 dist目录和打包内容是在内存中(更新快)
    • 位置 官网搜索 webpack-dev-server
    • 原理 使用http模块创建 8080 web服务
    • 默认以 public 文件夹作为服务器根目录
    • 根据配置, 打包相关代码在内存中(更新快),以output.path的值作为服务器根目录
    • 所以可以直接自己拼接访问 dist 目录下的内容

    步骤

    1. 下载 npm install --save-dev webpack webpack-dev-server
    2. 设置 设置默认为开发模式
    1. module.exports = {
    2. // 配置打包模式(使用相关内置优化)
    3. mode: 'development',
    4. ... ...
    5. };
    1. 配置 配置自定义命令
    1. "scripts": {
    2. ... ...
    3. "dev": "webpack server --open"
    4. },
    1. 启动 使用自定义命令启动开发服务器,体验代码热更新

    打包模式

    告诉webpack使用相应模式的内置优化

    设置方式

    1. 在webpack.config.js配置文件中设置mode选项
    2. 在package.json命令行设置mode参数 (推荐)
    3. 命令行设置的优先级高于配置文件的
    1. "scripts": {
    2. "build": "webpack --mode=production",
    3. "dev": "webpack server --open --mode=development"
    4. },

    条件打包

    在开发模式下应用 style-loader 内嵌css(更快), 在生产模式下提取css代码(并行下载)

    方法1

    1. webpack.config.js配置导出函数
    2. 具体代码参考官网, 搜索模式(Mode)
    3. 缺点: 局限性大, 只能区分2中模式(开发/生产)

    方法2

    1. 借助cross-env(跨平台通用) 包命令, 设置参数区分环境
    2. 安装 npm i cross-env --save-dev
    3. 配置自定义命令, 传入参数名和值 ( 会绑定到process.env对象中 ) (Node.js环境变量)
    1. "scripts": {
    2. "build": "cross-env NODE_ENV=production ... ",
    3. "dev": "cross-env NODE_ENV=development ..."
    4. },
    1. 在webpack.config.js 区分不同环境, 使用不同配置
    1. module.exports = {
    2. module: {
    3. rules: [
    4. // 提取css的配置
    5. {
    6. test: /\.css$/i,
    7. // 提取css插件
    8. // 根据不同环境, 使用不同的插件
    9. use: [
    10. process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader',
    11. "css-loader"
    12. ],
    13. },
    14. // less打包配置
    15. {
    16. test: /\.less$/i,
    17. use: [
    18. // 根据不同环境, 使用不同的loader
    19. process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader',
    20. 'css-loader',
    21. 'less-loader',
    22. ],
    23. },
    24. ],
    25. },
    26. };
    1. 重新打包
    2. 缺点: 如果不同模式的配置差异很大, 判断和配置起来就会比较麻烦

    方法3

    1. 配置不同的webpcak.config.js
    2. 适合多种模式差异性较大的情况

    注入环境变量

    cross-env 设置的环境变量只在Node,js环境生效, 前端代码无法访问

    解决

    1. 使用webpack内置的 DefinePlugin插件
    2. 位置 官网搜索 DefinePlugin
    3. 作用 在编译时, 将前端代码中匹配的变量名, 替换为值或表达式
    4. 配置
    1. const webpack = require('webpack');
    2. module.exports = {
    3. plugins: [
    4. // 前端注入环境变量
    5. new webpack.DefinePlugin({
    6. // key 是注入到打包后的前端JS代码中的全局变量名
    7. // value 是对应的变量值 ( 在 corss-env 注入在 node.js 中的环境变量字符串 )
    8. 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    9. }),
    10. ],
    11. };
    1. 使用
    1. /**
    2. * 在前端项目代码中
    3. * 开发模式下打印语句正常使用
    4. * 生产模式下打印语句失效
    5. */
    6. if (process.env.NODE_ENV === 'production') {
    7. console.log = function () { }
    8. }
    9. console.log('开发模式下可用, 生成模式下禁用');

    开发环境调错

    代码被压缩和混淆后, 无法正确定位源代码位置(行数和列数)

    解决

    1. source map(资源地图) : 可以准确追踪error和warning在原始代码位置
    2. inline-source-map选项: 把源代码的位置信息一起打包在JS文件内
    3. 其他选项: 官网搜索 devtool 查看
    4. 注意: 该配置仅适用于开发环境, 不要在生产环境使用(防止被轻易查看源码位置)
    1. const config = {...}
    2. if (process.env.NODE_ENV === 'development') {
    3. // 在开发环境中 配置sourcemap选项
    4. config.devtool = 'inline-source-map'
    5. }
    6. module.exports = config
    1. /**
    2. * 问题
    3. * error和 warning 的提示信息和实际错误位置不一致, 不方便调试
    4. * 解决
    5. * 启动 webpack 的 cource-map 资源地图功能, 获得准确的错误提示
    6. */
    7. consolee.warning('222');

    解析别名

    配置 import 引入路径的别名, 让引入资源更简单(而且使用绝对路径)

    在webpack.config.js中 配置解析别名 @ 来代表 src 绝对路径

    1. const config = {
    2. ... ...
    3. // 解析
    4. resolve: {
    5. // 配置别名
    6. alias: {
    7. '@': path.resolve(__dirname, 'src'),
    8. },
    9. },
    10. };
    11. module.exports = config

    CDN优化

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

    步骤

    1. 需求: 开发模式使用本地的第三方库, 生产模式下使用CDN加载引入
    2. CDN服务商: BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务
    3. 在html中引入 第三方库 的CDN地址 (使用模版语法区分环境)
    1. <head>
    2. ... ...
    3. <!-- 生成环境下使用cdn资源 -->
    4. <!-- 该模版语法由 HtmlWebpackPlugin 插件提供 -->
    5. <% if(htmlWebpackPlugin.options.useCdn){ %>
    6. <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
    7. <% } %>
    8. </head>
    9. <body>
    10. ... ...
    11. <!-- 生成环境下使用cdn资源 -->
    12. <% if(htmlWebpackPlugin.options.useCdn){ %>
    13. <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.6.8/axios.min.js"></script>
    14. <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.min.js"></script>
    15. <% } %>
    16. </body>
    1. 在 webpack 中配置 externals 外部扩展选项
    1. const config = {
    2. plugins: [
    3. new HtmlWebpackPlugin({
    4. ... ...
    5. // 自定义属性, 在html模版中 <%=htmlwebpackPlugin.options.useCdn%> 访问使用
    6. useCdn: process.env.NODE_ENV === 'production', // 是否使用CDN
    7. }),
    8. ],
    9. };
    10. // 在生产环境中
    11. if (process.env.NODE_ENV === 'production') {
    12. // 配置外部扩展选项 (让 webpack 防止 import的包被打包进dist文件 )
    13. config.externals = {
    14. // key -> 代码中 import from 后面的模版标识字符串
    15. // value -> 替换在原地的变量名 (要和 cdn暴露在全局的变量名一致)
    16. 'bootstrap/dist/css/bootstrap.min.css': 'bootstrap',
    17. 'axios': 'axios'
    18. }
    19. }
    20. module.exports = config
    1. webpack会给入口文件添加defer属性
    1. <head>
    2. ... ...
    3. <script defer="defer" src=".././login/index.js">script>
    4. ... ...
    5. head>

    多页面打包

    单页面: 单个html文件, 切换DOM的方式实现不同业务逻辑展示

    多页面: 多个html文件, 切换页面实现不同业务逻辑展示

    步骤

    1. 需求: 把黑马头条-数据管理平台-内容页面一起引入打包使用
    2. 把 content.html 文件放入public文件夹,作为模版文件
    3. 准备src/content文件夹, 放入配套的css和js文件
    4. 把auth.js文件放到utils文件夹
    5. 配置 webpack 多入口 和 多页面的位置
    1. const config = {
    2. // 自定入口文件
    3. entry: {
    4. 'login': path.resolve(__dirname, 'src/login/index.js'),
    5. 'content': path.resolve(__dirname, 'src/content/index.js'),
    6. },
    7. // 自定出口文件
    8. output: {
    9. // 文件位置
    10. path: path.resolve(__dirname, 'dist'),
    11. // 文件名称
    12. // [name]占位符, 读取entry 属性的key作为文件名
    13. filename: './[name]/index.js',
    14. },
    15. // 注册插件
    16. plugins: [
    17. // 自动生成HTML插件(页面1)
    18. new HtmlWebpackPlugin({
    19. // 插件配置
    20. template: path.resolve(__dirname, 'public/login.html'), // 模板文件
    21. filename: path.resolve(__dirname, 'dist/login/index.html'), // 输出文件
    22. // 自定义属性, 在html模版中 <%=htmlwebpackPlugin.options.useCdn%> 访问使用
    23. useCdn: process.env.NODE_ENV === 'production', // 是否使用CDN
    24. chunks: ['login'] // 引入哪些打包后的模块 (和 entry 属性的key一致)
    25. }),
    26. // 自动生成HTML插件(页面2)
    27. new HtmlWebpackPlugin({
    28. template: path.resolve(__dirname, 'public/content.html'), // 模板文件
    29. filename: path.resolve(__dirname, 'dist/content/index.html'), // 输出文件
    30. useCdn: process.env.NODE_ENV === 'production', // 是否使用CDN
    31. chunks: ['content']
    32. }),
    33. // 提取css插件
    34. new MiniCssExtractPlugin({
    35. filename: './[name]/index.css', // 输出文件
    36. }),
    37. ],
    38. };
    39. module.exports = config
    1. 运行/打包后, 测试效果

    步骤

    1. 需求: 把黑马头条-数据管理平台-发布文章页面一起引入打包使用
    2. 把 publish.html 文件放入public文件夹,作为模版文件
    3. CDN服务商: https://unpkg.com/form-serialize@0.7.2/index.js
    4. NPM包市场: npm | Home
    5. 准备src/publish文件夹, 放入配套的css和js文件
    6. 把editor.js文件放到utils文件夹
    7. 配置 webpack 多入口 和 多页面的位置
    1. const config = {
    2. // 自定入口文件
    3. entry: {
    4. ... ...
    5. 'publish': path.resolve(__dirname, 'src/publish/index.js'),
    6. },
    7. ... ...
    8. // 注册插件(提供更多功能)
    9. plugins: [
    10. ... ...
    11. // 自动生成HTML插件(页面3)
    12. new HtmlWebpackPlugin({
    13. template: path.resolve(__dirname, 'public/publish.html'), // 模板文件
    14. filename: path.resolve(__dirname, 'dist/publish/index.html'), // 输出文件
    15. useCdn: process.env.NODE_ENV === 'production', // 是否使用CDN
    16. chunks: ['publish']
    17. }),
    18. ... ...
    19. ],
    20. ... ...
    21. };
    22. // 在生产环境中
    23. if (process.env.NODE_ENV === 'production') {
    24. // 配置外部扩展选项 (让 webpack 防止 import的包被打包进dist文件 )
    25. config.externals = {
    26. // key -> 代码中 import from 后面的模版标识字符串
    27. // value -> 替换在原地的变量名 (要和 cdn暴露在全局的变量名一致)
    28. '@wangeditor/editor': 'wangEditor',
    29. 'form-serialize': 'serialize'
    30. }
    31. }
    32. module.exports = config
    1. 运行/打包后, 测试效果

    分割公共代码

    步骤

    1. 有些代码a页面用到了, b页面也用到了, 就需要提取出来, 而不是被重复打包
    2. 配置webpack的splitChunks分割功能
    1. const config = {
    2. // 优化配置
    3. optimization: {
    4. ... ...
    5. // 代码分割
    6. splitChunks: {
    7. chunks: 'all', // 所有模块动态非动态移入的都分割分析
    8. cacheGroups: { // 分隔组
    9. common: { // 提取公共模块
    10. minSize: 0, // 抽取chunk最小字节大小
    11. minChunks: 2, // 最小引用数
    12. reuseExistingChunk: true, // 当前 chunk 包含已从主 bundel 中拆分出的模块, 则它将被重用
    13. name(module, chunks, cacheGroupKey) { // 分离出模块文件名
    14. const allChunksNames = chunks.map((item) => item.name).join('~') // 模块名: 1~模块名
    15. return `./js/${allChunksNames}` // 输出到 dist 目录下位置
    16. },
    17. },
    18. },
    19. },
    20. },
    21. };
    22. module.exports = config
  • 相关阅读:
    ESB(企业服务总线)
    基于PLC的工业晾晒架系统
    mysql中的各种日志文件redo log、undo log和binlog
    vscode中git拉取、提交代码、解决冲突,以及合并代码的操作
    车身板(ABS)市场现状及未来发展趋势分析
    【Linux】环境变量
    进制转换数学函数之[CISCN 2019 初赛]Love Math
    HTML班级网页设计 基于HTML+CSS+JS制作我们的班级网页(web前端学生网页设计作品)
    oracle 19c 统计信息详解
    Python基础
  • 原文地址:https://blog.csdn.net/CSDN20221005/article/details/139430253