webpack 工程

76 阅读7分钟

实际的前端开发:

  • 模块化(js 的模块化、css 的模块化、资源的模块化)
  • 组件化(复用现有的 UI 结构、样式、行为)
  • 规范化(目录结构的划分、编码规范化、接口规范化、文档规范化、 Git 分支管理)
  • 自动化(自动化构建、自动部署、自动化测试)

目前主流的前端工程化解决方案:

webpack 的主要功能

它提供了友好的前端模块化开发支持,以及代码压缩混淆、处理浏览器端 JavaScript 的兼容性、性 能优化等强大的功能。

好处:让程序员把工作的重心放到具体功能的实现上,提高了前端开发效率和项目的可维护性。
注意:目前 Vue,React 等前端项目,基本上都是基于 webpack 进行工程化开发的。

创建项目

  1. 创建空白文件夹,然后在此处打开cmd
  2. 运行命令 npm init -y,得到 package.json文件
  3. 创建src源代码目录
  4. 在src中新建index.html 和 index.js
  5. 安装jquery,npm install jquery -s(记录到packjson中)
  6. 安装成功,在 package.json 中会显示

现在写代码会报错,因为没有配置webpack

为项目安装webpack,在此项目下cmd运行

  • D:表示安装到开发环境,是--save-dev缩写
npm install webpack@5.42.1 webpack-cli@4.7.2 -D
  • dependencies 表示发布环境,正式环境
  • devDependencies 表示开发环境
{
  "name": "clos",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "jquery": "^3.6.3"
  },
  "devDependencies": {
    "webpack": "^5.42.1",
    "webpack-cli": "^4.7.2"
  }
}

如何知道依赖安装到哪些环境

www.npmjs.com/ 搜索webpack,并查询

配置WebPack

  1. 创建文件 webpack.config.js在根目录 在 webpack.config.js 中
  • development 不会进行压缩,会进行兼容
  • production 会压缩,会兼容
// 使用Node.js 中的导出语法,向外导出一个Webpack的配置对象
module.exports = {
    // 代表webpack运行的模式,可选值有两个 development 和 production
    mode: 'development'
}
  1. 在 package.json 的 scripts 节点下,新增 dev 脚本如下:

可以通过 npm run dev 执行,dev是名称

"scripts": {
    "dev": "webpack" 
  },
  1. 打开终端输入 npm run dev 执行

运行完毕后,会生成dist文件夹,里面是经过处理的文件,引入这个解决兼容性问题

mode 作用

mode 节点的可选值有两个,分别是:

  1. development
    • 开发环境
    • 不会对打包生成的文件进行代码压缩和性能优化
    • 打包速度快,适合在开发阶段使用
  2. production
    • 生产环境
    • 会对打包生成的文件进行代码压缩和性能优化
    • 打包速度很慢,仅适合在项目发布阶段使用

webpack.config.js

webpack.config.js 是 webpack 的配置文件。
webpack 在真正开始打包构建之前,会先读取这个配置文件,从而基于给定的配置,对项目进行打包。

在 webpack 4.x 和 5.x 的版本中,有如下的默认约定:

  1. 默认的打包入口文件为 src -> index.js
  2. 默认的输出文件路径为 dist -> main.js 注意:可以在 webpack.config.js 中修改打包的默认约定

修改默认处理文件和生成文件

// 使用node 定义path
const path = require("path");
module.exports = {
    // 指定处理那个文件
    entry: path.join(__dirname,'src1/index.js'),
    // 指定生成的文件要存放到哪里
    output: {
        // 存放的目录
        path: path.join(__dirname,"dist"),
        // 生成的文件名
        filename: 'bundle.js'
    }
}

插件

热更新(webpack-dev-serve)

安装热更新,在项目的文件cmd

npm install webpack-dev-server@3.11.2 -D

在 package.json 文件中,修改

  • 添加serve
"scripts": {
  "dev": "webpack serve"
},

然后启动

如果报错

Unable to load '@webpack-cli/serve' command [webpack-cli] TypeError: options.forEach is not a function

需要先执行

npm install webpack-cli -D
npm run dev

这个时候发现是刷新了,但是内容没有更换啊,这是因为需要用端口打开不能本地打开了

打开后还是没有,根据下方信息说明,生成在根目录有个main.js,但是看不到啊

image.png

原因是没有放到物理磁盘上,生成到内存里啦,引入内存里的就可以啦

复制首页

这个时候我们发现,我打开端口,显示的是目录,这显然是不对的。需要复制src的首页到根目录区(内存中)

  • 特性:会帮助我们自动导入内存中的js文件。

运行

npm install html-webpack-plugin@5.3.2 -D

配置插件

// 导入html-webpack-plugin这个插件
const HtmlWebpackPlugin = require("html-webpack-plugin");
// new 构造函数,创建实例对象
let webpackPlugin = new HtmlWebpackPlugin({
    // 指定要复制那个插件
    template: './src/index.html',
    // 复制到哪里
    filename: './index.html'
});
module.exports = {
    // 插件的数组,将来webpack运行时会加载这些插件
    plugins: [webpackPlugin]
}

配置启动信息

module.exports = {
    devServer: {
        // 运行成功,自动打开浏览器
        open: true,
        // 指定端口
        port: 80,
        // 指定主机地址
        host: '127.0.0.1'
    }
}

处理CSS

在实际开发过程中,webpack 默认只能打包处理以 .js 后缀名结尾的模块。其他非 .js 后缀名结尾的模块, webpack 默认处理不了,需要调用 loader 加载器才可以正常打包,否则会报错!

loader 加载器的作用:协助 webpack 打包处理特定的文件模块。

  • css-loader 可以打包处理 .css 相关的文件
  • less-loader 可以打包处理 .less 相关的文件
  • babel-loader 可以打包处理 webpack 无法处理的高级 JS 语法

image.png

不配置会报错

执行过程

  1. 当webpack发现处理不了的文件时,会查找webpack.config.js 这个配置文件
  2. 看到module.ruls数组中,是否配置了对应的loader加载器
  3. webpakc把文件,先交给最后一个loader进行处理,处理完再交给前一个
  4. 发现没有loader了会将处理结果交给webpack
  5. webpack把处理结果合并到main.js文件中,生成打包好的文件

运行命令

npm i style-loader@3.0.0 css-loader@5.2.6 -D

配置loader

在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

module.exports = {
    // 所有第三方文件模块的匹配规则
    module: {
        // 文件后缀名的匹配规则
        rules: [
            // 匹配.css结尾的,使用这两个loader
            {test: /\.css$/, use: ['style-loader', 'css-loader']}
        ]
    }
}

处理less

运行命令

npm i less-loader@10.0.1 less@4.1.1 -D

在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

module.exports = {
    // 所有第三方文件模块的匹配规则
    module: {
        // 文件后缀名的匹配规则
        rules: [
            // 匹配.less结尾的,使用这三个loader
            {test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']}
        ]
    }
}

导入图片并使用

图片使用 base64 的好处

  • 减少不必要的请求
// 在JS中引入他
import logo from '/src/image/微信图片_20220718233747.jpg'
$(function () {
    // 使用它
    $('.logo').attr('src', logo)
})

会报错,因为没有装插件

运行命令

npm i url-loader@4.1.1 file-loader@6.2.0

配置依赖

  • limit表示字节,超过这个字节将不会再转换base64
module: {
    // 文件后缀名的匹配规则
    rules: [
        {test: /.jpg|png|gif$/, use: 'url-loader?limit=22229'}
    ]
}

处理高级语法

像下面这些高级语法,太高级了,webpack根本处理不了,需要加插件

// 定义装饰器函数
function info(target){
    target.info = "Person info"
}

// 定义普通类
@info
class Person{}

console.log(Person.info)

运行命令

npm i babel-loader@8.2.2 @babel/core@7.14.6 @babel/plugin-proposal-decorators@7.14.5 -D

配置信息

module.exports = {
    // 所有第三方文件模块的匹配规则
    module: {
        // 文件后缀名的匹配规则
        rules: [
            // 使用babel-loader 处理高级的js语法
            // 一定要排除 node_modules 目录,因为第三方的包,不需要关心
            {test: /.js$/, use: 'babel-loader', exclude: /node_modules/}
        ]
    }
}

在根目录下创建 babel.config.js 文件,在里面写

module.exports = {
    //声明 babel 可用的插件
    // 将来, webpack 在调用 babel-loader 的时候,先加载 plugins插件来使用
    plugins: [['@babel/plugin-proposal-decorators', {legacy: true}]]
}

详情请参考 Babel 的官网 babeljs.io/docs/en/bab…

打包

项目开发完成之后,需要使用 webpack 对项目进行打包发布,主要原因有以下两点:

  1. 开发环境下,打包生成的文件存放于内存中,无法获取到最终打包生成的文件
  2. 开发环境下,打包生成的文件不会进行代码压缩和性能优化

在package.json中配置一下即可

"scripts": {
  "dev": "webpack serve",
  // 项目发布时,运行build命令
  // --mode 表示配置环境,为生产环境,会压缩代码,不会使用内存。
  "build": "webpack --mode production"

JS文件生成到dict/js文件夹中

添加一层目录即可

output: {
    filename: "js/main.js"
},

图片应该在dict/image文件夹中

  • &outputPath=images' 加上这个
module.exports = {
    // 所有第三方文件模块的匹配规则
    module: {
        // 文件后缀名的匹配规则
        rules: [
            {test: /\.jpg|png|gif$/, use: 'url-loader?limit=22229&outputPath=images'}
        ]
    }
}

自动删除dict目录插件

运行命令

npm install clean-webpack-plugin@3.0.0 -D

在 webpack.config.js 文件中配置插件

// 导入自动清理插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin')

安装

注意 output 中 path: path.join(__dirname,"dist") 必须配置,要不然找不到

module.exports = {
    // 代表webpack运行的模式,可选值有两个 development 和 production
    mode: 'development',
    // 插件的数组,将来webpack运行时会加载这些插件,安装自动清理插件
    plugins: [webpackPlugin, new CleanWebpackPlugin()],
}

生成信息

开发环境下默认生成的 Source Map,记录的是生成后的代码的位置。会导致运行时报错的行数与源代码的行 数不一致的问题。

  • 在发布的时候尽量关闭这个功能,保证数据安全
module.exports = {
    // 代表webpack运行的模式,可选值有两个 development 和 production
    mode: 'development',
    // 配置信息矫正
    devtool: 'eval-source-map',

我们希望根据行号,看源码进行调试,但是浏览器点击还是一行显示。折中方案

  • 加上之后,无法从浏览器看到源码,但是可以看到行号
  • source-map这个属性可以看到源码,非常不安全
module.exports = {
    // 代表webpack运行的模式,可选值有两个 development 和 production
    mode: 'development',
    devtool: 'nosources-source-map',
}

导包

导入包的时候建议使用@号,从src开始找

module.exports = {
    resolve: {
        alias: {
            // 告诉webpack 程序员写的代码 @,表示src
            '@': path.join(__dirname,'./src/')
        }
    }
}