WebPack

1. Webpack 介绍

1-1 什么是 Webpack

Webpack 是一个模块打包器 (bundler),本身是一个工具。 https://webpack.docschina.org/

在 Webpack 看来,前端所有的静态资源文件都是模块,如 JS / JSON / CSS / IMG / LESS / FONTS 等等,这些文件都会作为模块来处理。

Webpack 会根据模块之间的依赖关系,进行分析打包,生成最终的静态资源。

1-2 五个核心概念

Webpack 有五个核心的概念需要知道,分别是

  • Entry 入口
  • Output 出口
  • Loader 加载器
  • Plugins 插件
  • Mode 模式
Entry 入口

入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点依赖的

Output 出口

Output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件

Loader 加载器

Webpack 默认只能处理 JS / JSON 文件,如果需要打包其他类型文件,就需要使用对应的 loader 进行处理。例如 css-loader,less-loader,file-loader 等等

Loader 本质是 JS 函数,接受源文件内容,返回转换后的结果

Plugins 插件

loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量

Mode 模式

Webpack 主要有两种工作模式,分别是 development 开发模式和 production 生产模式。

2. 安装 Webpack

全局安装

npm install webpack webpack-cli -g

局部安装

npm init 
npm install webpack webpack-cli -D                # cli  client

这里推荐使用『局部安装』,这样可以避免因为版本不同而产生的 BUG

3. Webpack 初体验

  1. 创建 JS 文件

    • src/js/app.js 入口文件
    • src/js/m1.js 模块文件
    • src/index.html HTML 文件
  2. 安装

    npm install webpack webpack-cli -D 
    
  3. 执行打包命令 『项目根目录下运行』

    npx webpack --entry ./src/js/app.js  --output-path ./build/js --output-filename bundle.js --mode development
    
    • –entry 设置入口
    • –output-path 设置输出目录
    • –output-filename 设置输出文件名
    • –mode 设置运行模式
  4. HTML 文件引入 『…/build/js/bundle.js』

  5. 搞定

    初体验需要改进的地方:

    1. 打包命令太复杂
    2. 不能将 ES6 转为 ES5
    3. 只能打包 JS 和 JSON, 不能打包其他类型的文件

4. 使用配置文件打包

项目根目录下创建文件 『webpack.config.js』,内容如下:

const {resolve} = require('path');
//暴露对象
module.exports = {
    //设置入口
    entry: './src/js/app.js',
    //设置出口
    output: {
        path: resolve(__dirname, 'build'),
        filename: 'js/bundle.js',
        clean: true, // 打包时, 可以清空目录
    },
    // 设置模式
    mode: 'development',
}

创建完毕之后,在项目根目录执行如下命令:

npx webpack

5. 打包 css 文件

  1. 首先先创建 HTML 结构与对应的 CSS 文件样式
  2. 在入口 JS 文件中, 引入 CSS 文件
import '../css/app.css'		
  1. 安装 loader
npm i style-loader css-loader -D
  1. 修改 webpack.config.js 配置文件
const {resolve} = require('path');
module.exports = {
    .
    .
    .
    mode: 'development',
    //配置 loader
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    "style-loader",		// 将 CSS 生成 style 标签插入 HTML 中
                    "css-loader"  		// 将 CSS 转为 CommonJS 的模块
                ]
            }   
        ]
    }
}
  1. 运行打包命令 『在项目的根目录下运行』
npx webpack

6. 打包 less 文件

  1. 首先编写 HTML 结构以及 LESS 文件样式
  2. JS 文件导入 LESS 文件
import "../less/app.less"
  1. 安装 loader
npm i less less-loader -D
  1. 配置 loader
const {resolve} = require('path');
module.exports = {
    .
    .
    .
    mode: 'development',
    module: {
        rules: [
            .
  			.
  			.
  			//配置 less 文件处理
            {
                test: /\.less$/,
                use: [
                    "style-loader",
                    'css-loader',
                    'less-loader'
                ]
            } 
        ]
    }
}	
  1. 执行打包命令
npx webpack

7. JS 代码质量检查

ESLint(https://eslint.bootcss.com/) 能对 JS 基本语法错误 / 隐患进行提前检查。

ESlint 不能检查 JS 运行时错误,因为并没有执行 JS 代码

使用步骤如下:

  1. 安装插件
npm i eslint eslint-webpack-plugin -D
  1. 修改 webpack.config.js 配置文件
const {resolve} = require('path');
//1. 导入插件
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
    .
    .
    .
    mode: 'development',
    module: {
        .
  		.
  		.
    },
  	//2. 配置插件
  	plugins: [
        new ESLintPlugin()
    ]
}
  1. 项目根目录下创建 eslint 配置文件 『.eslintrc.js』
module.exports = {
    "parserOptions": {
        "ecmaVersion": 6, 				// 支持es6
        "sourceType": "module"			// 使用es6模块化
    },
    "env": { 							// 设置环境
        "browser": true,   				// 支持浏览器环境: 能够使用window上的全局变量
        "node": true       				// 支持服务器环境:  能够使用node上global的全局变量
    },
    "globals": {						// 声明使用的全局变量, 这样即使没有定义也不会报错了
        "$": "readonly"					// $ 不允许重写变量
    },
    "rules": {  						// eslint检查的规则  0 忽略 1 警告 2 错误
        "no-console": 0, 				// 不检查console
        "eqeqeq": 0,					// 用 == 而不用 === 就报错
        "no-alert": 0 					// 不能使用alert
    },
    "extends": "eslint:recommended" 	// 使用eslint推荐的默认规则
 }

  1. 执行打包命令
npx webpack

8. JS 语法转换

Babel 可以将浏览器不能识别的新语法(ES6-11)转换成原来识别的旧语法(ES5),浏览器兼容性处理。 操作流程:

  1. 安装 loader
npm i babel-loader @babel/core @babel/preset-env -D

  • @babel/core babel 的核心库
  • @babel/preset-env babel 的预设工具包,将所有新语法转为 ES5
  • babel-loader babel 在 webpack 中的 loader 包
  1. 配置 loader
.
.
.
module.exports = {
    .
  	.
  	.
    mode: 'development',
    module: {
        rules: [
            .
  			.
  			.
  			//配置 babel 的 loader
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            } 
        ]
    }
}

  1. 设置目标浏览器

    修改项目根目录下的 package.json

    {
    	"browserslist": [
    		"last 10 versions"
    	]
    }
    
    
  2. 执行打包命令

npx webpack

9. JS 兼容性处理

9-1 Polyfill

babel 完成了新语法到旧语法的转换,如 let / const / 箭头函数等,但是新加入的 API 却没有处理,例如 Promise / Array.from / Array.prototype.find / Array.prototype.fill 等等

Polyfill 是一块代码(通常是 Web 上的 JavaScript),用来为旧浏览器提供它没有原生支持的较新的功能。单词原意: 温暖的填充物

  1. 安装 polyfill
npm i @babel/polyfill

  1. 入口文件引入 polyfill
import '@babel/polyfill';

  1. 执行打包
npx webpack

注意: webpack5 打包生成的 JS 代码默认是被包裹在『箭头函数』中,这样 IE 无法执行最终代码,此时需要配置目标浏览器,见附录

9-2 core-js

使用 polyfill 会使得代码的体积变大, 这时可以使用 core-js 来实现按需打包,减小打包文件的体积。

  1. 安装 core-js
npm i core-js

  1. 修改 babel-loader 的配置
.
.
.
module.exports = {
    .
  	.
  	.
    mode: 'development',
    module: {
        rules: [
            .
  					.
  					.
  			//配置 babel 的 loader
            {
              test: /\.js$/,
              exclude: /(node_modules)/,
              use: {
                loader: 'babel-loader',
                options: {
                  presets: [
                    [
                      '@babel/preset-env',
                      {
                        useBuiltIns: 'usage',  // 按需引入(需要使用polyfill)
                        corejs: { version: 3 }
                      }
                    ]
                  ]
                }
              }
            }
        ]
    }
}

  1. 移除入口文件中的 『import ‘@babel/polyfill’』
  2. 执行打包命令
npx webpack

10. 打包 CSS 中的图片资源

  1. 首先编写 HTML 与 CSS 背景图片
  2. 修改 webpack.config.js
.
.
.
module.exports = {
    .
  	.
  	.
    mode: 'development',
    module: {
        rules: [
            .
  			.
  			.
  			//配置背景图片的处理
            {
                test: /\.(jpg|png|gif)$/,
                type: "asset", // 资产,当成资源来处理
                //解析器
                parser: {
                    //转base64的条件
                    dataUrlCondition: {
                        maxSize: 8 * 1024, // 8kb
                    }
                },
                //生成文件
                generator: {
                		//打包保存的文件名称
                    filename: 'images/[hash:6][ext]',
                },
            },
        ]
    }
}

  1. 执行打包
npx webpack

11. 打包 HTML 文件

webpack 可以将原始的 HTML 打包处理,生成优化后的结果

  1. 安装插件
npm i html-webpack-plugin -D

  1. 修改 webpack.config.js 配置文件
const { resolve } = require('path');
const ESLintPlugin = require('eslint-webpack-plugin');
// 1. 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    module: {
        .
        .
        .
    },
    //2. 配置插件
    plugins: [
        .
        .
        .
        new HtmlWebpackPlugin({
            template: "./src/index.html",// 指定html模板文件。
            inject: "body",// 将打包生成的JS文件放置在body尾部
            hash: true,// 在引入JS时增加hash后缀字符串,去除缓存。
            minify: {
                removeAttributeQuotes: true,// 移除属性中的双引号
                removeComments: true,// 移除注释
                collapseWhitespace: true,// 去除空格与换行
            }
        })
    ]
}

12. 打包 IMG 图片

HTML 中会使用 IMG 标签来引入一些图片,这些图片也需要 『 html-loader 』 来进行处理。

  1. 删除 src/index.html 文件中的 JS 引入 『这一步一定要做』
  2. HTML 结构中引入图片
<img src="./images/react.png" alt="">

  1. 安装 loader
npm i html-loader -D

  1. 配置 loader
.
.
.
module.exports = {
    .
    .
    .
    module: {
        rules: [
            .
            .
            .
			// 配置 html 的 loader
            {
                test: /\.(html)$/,
                use: {
                    loader: 'html-loader'
                }
            }
        ]
    }
}

  1. 执行打包

    npx webpack
    
    

12. 打包字体图标

这里以 iconfont 为例,首先先下载一个项目,然后按照如下流程操作:

  1. 将字体文件复制到 src/fonts 目录下
  2. 复制 CSS 代码到样式文件中,这里可以是 CSS 文件,也可以是 LESS 文件
@font-face {
  font-family: "iconfont";
  src: url("../fonts/iconfont.eot");
  src: url("../fonts/iconfont.eot?#iefix") format("embedded-opentype"),
    url("../fonts/iconfont.woff2") format("woff2"), url("../fonts/iconfont.woff") format("woff"),
    url("../fonts/iconfont.ttf") format("truetype"),
    url("../fonts/iconfont.svg#iconfont") format("svg");
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}


  1. HTML 结构中创建对应的 span 标签
<span class="iconfont">&#xe8ab;</span>

  1. 修改 webpack.config.js 配置文件
.
.
.
module.exports = {
    .
  	.
  	.
    mode: 'development',
    module: {
        rules: [
           	.
          	.
          	.
  			//配置字体文件的处理
            {
                test: /\.(eot|svg|woff|woff2|ttf)$/,  
                type: 'asset/resource', // 只能单纯的保存文件
                generator: {
                    filename: 'fonts/[hash:6][ext]',
                },
            }
        ]
    },
}

  1. 运行打包命令
npx webpack

13. 自动编译打包运行

之前的操作,每次修改代码都需要重新执行 npx webpack 命令,这里我们可以使用 webpack-dev-server 自动打包运行

  1. 安装 webpack-dev-server
npm i webpack-dev-server -D

  1. 修改 webpack.config.js 配置文件
.
.
.
module.exports = {
    .
    
    output: {
        path: resolve(__dirname, 'build'),
        filename: 'js/bundle.js',
        clean: true,
        //1. 设置出口,设置页面中相关资源『css js 图片 JSON 字体』访问的路径都是以/开头的,目前不设置没事,但最终打包上线的时候需要加上,否则会出问题
        publicPath: '/'
    },
    .
    module: {
        .
        .
        .
    },
    plugins: [
        .
        .
        .
    ],

    //2. 配置开发服务
    devServer:{
        port:3000,// 设置端口号
        open:true,// 自动在浏览器中打开页面
        compress:true,// false 关闭 gzip 压缩, true 开启(默认)
    }
}

  1. 运行启动命令
npx webpack-dev-server

14. devtool 配置

devtool 可以控制 source-map 的生成,source-map 一般是独立文件,映射原始的 JS 文件,方便定位调试错误。

.
.
.
module.exports = {
    
    plugins: [
        .
        .
        .
    ],

    devServer:{
    		.
        .
        .
    },

    //devtool
	//开发模式下使用 cheap-module-source-map
  	//生产模式  source-map 或者 不设置 devtool
	devtool: 'cheap-module-source-map',
}

15. 分离配置文件

webpack 可以使用不同的配置文件进行打包。操作步骤如下:

  1. 根目录下创建文件夹 config,将 webpack.config.js 复制两份
    • ./config/webpack.dev.js
    • ./config/webpack.prod.js
  2. 修改 webpack.prod.js
.
.
.
module.exports = {
    entry: './src/js/app.js',
  	output: {}
  	.
  	.
  	.
    
    // 1. 设置模式
    mode: 'production',
  	// 2. 删除 devServer 设置
  	// 3. 删除 devtool 设置
}

  1. 修改 package.json,增加命令别名配置
{
	.
	.
	.
	"scripts": {
        "start": "npx webpack-dev-server --config ./config/webpack.dev.js",
        "build": "npx webpack --config ./config/webpack.prod.js"
   }
   .
   .
   .
}


  1. 运行命令
npm run start
npm run build    

16. 分离 CSS 代码

前面的 CSS 样式代码都是放在 style 标签中,这里可以借助 mini-css-extract-plugin 抽离 CSS 文件

  1. 安装工具包
npm i mini-css-extract-plugin -D

  1. 修改 webpack.prod.js
.
.
.
//1. 引入插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    entry: './src/js/app.js',
    mode: 'production',
    module: {
        rules: [
        		//2. 修改 loader, 将之前的 style-loader 换为 MiniCssExtractPlugin.loader
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader'
                ]
            },
           	.
            .
            .
        ]
    },
    plugins: [
        .
        .
        .
        // 3. 配置插件
        new MiniCssExtractPlugin({					
            filename: "css/[hash:8].css",
        }),
        
    ]
}

  1. 运行打包命令
npm run build

17. CSS 兼容性处理

webpack 中可以使用 postcss 对 CSS 预处理,包括 CSS 兼容性处理

  1. 安装相关工具包
npm i postcss-loader autoprefixer -D

  1. 修改 webpack.prod.js 中的 loader 设置
.
.
.
module.exports = {
    entry: './src/js/app.js',
    mode: 'production',
    module: {
        rules: [
        		//在 css-loader 之前添加 postcss-loader
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    'postcss-loader',
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'less-loader'
                ]
            },
           	.
            .
            .
        ]
    },
   
}

  1. 项目根目录下创建 postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}

  1. 修改 package.json,增加 browserslist 属性
{
  .
  .
  .
  "browserslist": [
    "last 2 versions"
  ]
}

  1. 执行打包命令
npm run build

18. CSS 压缩

css-minimizer-webpack-plugin 插件可以压缩 CSS 代码,操作步骤如下:

  1. 安装插件
npm i css-minimizer-webpack-plugin -D

  1. 修改配置文件
.
.
.
//1. 引入插件
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');


module.exports = {
    .
    .
    .
    mode: 'production',
    .
    .
    .
    //2. 设置优化选项
    optimization: {
        minimizer: [new CssMinimizerPlugin()],
    },
}

  1. 执行打包命令
npm run build

19. JS 压缩

terser-webpack-plugin插件可以压缩 JS 代码,webpack5 版本不需要额外安装,操作步骤如下:

  1. 修改配置文件 webpack.prod.js

    .
    .
    .
    //1. 引入插件
    const TerserPlugin = require("terser-webpack-plugin");
    
    
    module.exports = {
        .
        .
        .
        mode: 'production',
        .
        .
        .
        //2. 设置优化选项
        optimization: {
            minimizer: [
      			new CssMinimizerPlugin(),
                new TerserPlugin()
            ],
        },
    }
    
    
  2. 运行打包

    npx webpack
    
    

附录

browserslist

browserslist 目标浏览器配置表,可以针对目标浏览器进行编译处理,避免不必要的兼容代码

browserslist 配置的方法有两种,一种是修改 『package.json』 配置,一种创建 『.browserslistrc』 文件

  1. package.json 形式
{
	.
	.
	.
	"browserslist": [
        ">0.2%",
        "not dead",
        "not op_mini all"
    ]
}

  1. 项目根目录下创建『.browserslistrc』 文件
> 1%
last 2 versions

配置规则介绍

规则介绍
> 1%全球超过1%人使用的浏览器
> 5% in US指定国家使用率覆盖
last 2 versions所有浏览器兼容到最后两个版本根据CanIUse.com追踪的版本
Firefox > 20指定浏览器的版本范围
not ie <=8排除 ie8 及以下
Firefox 12.1指定浏览器的兼容到指定版本
since 20132013年之后发布的所有版本
not dead with > 0.2%仍然还在使用且使用率大于 0.2%
last 2 Chrome versions最新的两个 Chrome 配置
cover 99.5%99.5% 的浏览器都是目标

https://caniuse.com/ 查看兼容性的网站

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wj18740503137

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值