meface/docs/article/web/tool/webpackTool.md

342 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 'Webpack'
date: 2020-10-10
author: 'ac'
tags:
- Webpack
categories:
- Web
---
## 1.前端工程化
实际的前端开发:
- 模块化js模块化、css模块化、资源的模块化
- 组件化UI结构、样式、行为的复用
- 规范化(目录的结构划分、编码规范化、接口规范化)
- 自动化(自动构建、部署、测试)
`前端工程化`指的是:在企业级的前端项目开发中,把前端开发所需的**工具**、**技术**、**流程**、**经验**等进行规范化、
标准化。
好处:前端开发自成体系,有一套标准的开发方案和流程。
工程化解决方案:
- [webpack](https://www.webpackjs.com/)
- parcel
## 2. Webpack的基本使用
> webpack 是前端项目工程化的具体解决方案。
Webpack是前端资源加载/打包工具,它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。 Webpack 可以将多种静态资源 js、css、less 转换成一个静态文件,减少了页面的请求。
主要功能:它提供了友好的前端**模块化**开发支持,以及**代码压缩混淆**、处理浏览器端 JavaScript 的**兼容性**、**性能优化**等强大的功能。
**Webpack 全局安装**
```shell
npm install webpack -g
```
到了 webpack4命令行相关的内容都移到 webpack-cli所以还需要安装 webpack-cli
```shell
npm install webpack-cli -g
```
Webpack 根据模块的依赖关系进行静态分析,这些文件(模块)会被打包到 bundle.js 文件中。
Webpack 会给每个模块分配一个唯一的 id 并通过这个 id 索引来访问模块。
---
下面通过一个项目来手动配置`Webpack`的方式来学习:
1. 创建一个空文件夹,运行`npm init -y`,初始化一个包管理配置文件`package.json`创建src目录并src下创建index.html和index.js
<img src="./images/image-20210907163730010.png" alt="image-20210907163730010" style="zoom:67%;" />
2. 安装jquery使用jq来操作DOM`npm i jquery -S`
```javascript
import $ from "jquery"
$(function(){
$("p").css("background-color","red");
})
```
3. 创建webpack.config.js配置文件
```js
module.exports = {
mode : "development" // 选择 development 为开发模式, production 为生产模式
}
```
4. 在`package,json`配置文件中添加脚本命令,运行`npm run dev`项目中的会从默认`src/index.js`文件作为入口,打包项目中的引用到的资源文件,并将结果输出到`dist/main.js`文件中。
```js
"scripts": {
"dev": "webpack"
},
```
<img src="./images/image-20210907171728757.png" alt="image-20210907171728757" style="zoom: 80%;" />
5. 将`index.html`文件中对`index.js`的引用修改为引用`dist/mian.js`,在浏览器中打开就可以看到效果。
<img src="./images/image-20210907172008755.png" alt="image-20210907172008755" style="zoom:80%;" />
### 2.1 配置文件
在执行`webpack`命令时webpack会去寻找项目中的webpack.config.js配置文件根据配置项对项目进行打包。
- 入口entry入口会指示 webpack 应该使用哪个模块来作为构建其内部依赖图的开始。进入入口起点后webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
- loader让 webpack 可以去处理那些非 JavaScript 文件。
- output属性告诉webpack在哪里输出path它创建的bundles以及如何命名这些文件filename
- 插件plugins
> 在`webpack4.x`和`webpack5.x`的版本中有默认的打包入口文件(`src/index.js`)和默认的输出文件路径(`dist/main.js`
```javascript
const path = require('path');
// 使用 Node.js 中的导出语法,向外导出一个 webpack 的配置对象
module.exports = {
//SourceMap 源码与压缩文件的映射文件,生成阶段建议关闭
devtool: "eval-source-map",
// development 为开发模式, production 生产模式(会压缩混淆代码)
mode: "development",
//指定要处理入口文件
entry: path.join(__dirname,"./src/index.js"),
// 指定生成的文件要存放到哪里
output: {
// 存放的目录
path:path.resolve(__dirname, 'dist/js/'), //表示当前执行脚本所在的目录。(路径)
// 生成的文件名
filename: "bundle.js"
}
};
```
### 2.2插件
插件在 webpack 的配置信息 plugins 选项中指定,用于完成一些 loader 不能完成的工作。常用插件:
1. `webpack-dev-server`:当修改源码时,项目自动打包和构建
```shell
npm install webpack-dev-server --save-dev
```
2. `html-webpack-plugin`:项目首次构建完成后自动打开项目文件
```shell
npm i --save-dev html-webpack-plugin
```
3. `clean-webpack-plugin`:清除每次打包的输出目录(`dist`)中原有的文件
```shell
npm install --save-dev clean-webpack-plugin
```
插件`dev-server`的使用:
需要在package.json文件中的脚本命令中添加serve参数
```javascript
"scripts": {
"dev": "webpack serve",
},
```
> dev-server插件会启动一个实时打包的http服务所以打开项目的时候是http协议开头
在`webpack.config.js`文件中`dev-server`插件可以通过`devserver`节点配置地址和端口:
```javascript
"devserver":{
open: true,
host: '127.0.0.1',
port: 9527
}
```
![image-20220218111225479](./images/image-20220218111225479.png)
![image-20220218111548844](./images/image-20220218111548844.png)
> `dev-server`插件会在内存中创建打包好的`bundle.js`文件,没有存储在物理磁盘中。首页中也会引入内存中的`bundle.js`文件
插件`html-webpack-plugin`的使用:
需要在`webpack.config.js`文件中进行配置
```javascript
// 1. 导入 html-webpack-plugin 这个插件,得到插件的构造函数
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 构造函数,创建插件的实例对象
const htmlPlugin = new HtmlPlugin({
// 指定要复制哪个页面
template: './src/index.html',
// 指定复制出来的文件名和存放路径
filename: './index.html'
})
module.exports = {
...
//3. 将插件实例对象配置到webpack中
plugins:[htmlPlugin]
...
}
```
插件`clean-webpack-plugin`的使用:
跟上一个插件方法一样,也是创建插件实例,配置`plugins`配置项.
```javascript
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
...
//3. 将插件实例对象配置到webpack中
plugins:[htmlPlugin,new CleanWebpackPlugin()]
...
}
```
完成的配置文件如下:
```javascript
const path = require('path');
// 1. 导入 html-webpack-plugin 这个插件,得到插件的构造函数
const HtmlPlugin = require('html-webpack-plugin')
// 2. new 构造函数,创建插件的实例对象
const htmlPlugin = new HtmlPlugin({
// 指定要复制哪个页面
template: './src/index.html',
// 指定复制出来的文件名和存放路径
filename: './index.html'
})
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// 向外导出一个 webpack 的配置对象
module.exports = {
//SourceMap 源码与压缩文件的映射文件生成阶段建议关闭可选值source-map、eval-source-map、nosources-source-map。若配置了该项则打包会生成一个记录映射关系的*.map文件
devtool: "nosources-source-map",
// development 为开发模式, production 生产模式(会压缩混淆代码)
mode: "development",
//指定要处理入口文件
entry: "./src/index.js",
// 指定生成的文件要存放到哪里
output: {
// 存放的目录
path:path.resolve(__dirname, 'dist'), //表示当前执行脚本所在的目录。(路径)
// 生成的文件名
filename: "js/bundle.js"
},
devServer: {
open: true,
host: '127.0.0.1',
port: 9527
},
// 插件的数组,将来 webpack 在运行时,会加载并调用这些插件
plugins: [htmlPlugin, new CleanWebpackPlugin()],
};
```
### 2.3 loader
Webpack 本身只能处理 JS文件如果要处理其他类型的文件**就需要使用 loader 进行转换**。 比如加载CSS文件需要使用css-loader和style-loader
- css-loader:遍历css文件找到url()表达式;
- style-loader:将css代码嵌入页面中的一个style标签中
![image-20220218112340763](./images/image-20220218112340763.png)
常用的`loader`
1. 样式相关的`css-loader`、`style-loader`、`less-loader`
2. 路径相关的`url-loader`、`file-loader`
3. `ES6`相关的`babel-loader`,使用`bable`需要创建一个`babel.config.js`配置文件(设置转码规则)
```javascript
//css相关的包
npm install --save-dev css-loader
npm install --save-dev style-loader
//less相关的包
npm install less less-loader --save-dev
//图片相关的包
npm install url-loader --save-dev
npm install file-loader --save-dev
//Babel相关的包
npm install -D babel-loader @babel/core @babel/plugin-proposal-decorators
```
在`webpack.config.js`文件中的`module`节点添加一个`rules`数组用于添加loader规则
```javascript
module: {//所有第三方文件模块的匹配规则
rules: [// 定义了不同模块对应的 loader
//处理css文件的loader,注意loader的顺序执行顺序是从后往前的先css-loader处理将结果交给style-loader最后再交给webpack打包到bundle.js文件中
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
// 处理 .less 文件的 loader
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
// 处理图片文件的 loader
// 如果需要调用的 loader 只有一个则只传递一个字符串也行如果有多个loader则必须指定数组
// 在配置 url-loader 的时候,多个参数之间,使用 & 符号进行分隔
{ test: /\.jpg|png|gif$/, use: 'url-loader?limit=880&outputPath=images' },
// 使用 babel-loader 处理高级的 JS 语法
// 在配置 babel-loader 的时候,程序员只需要把自己的代码进行转换即可;一定要排除 node_modules 目录中的 JS 文件
// 因为第三方包中的 JS 兼容性,不需要程序员关心
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
]
},
resolve: {
alias: {
// 告诉 webpack程序员写的代码中@ 符号表示 src 这一层目录,这样查找资源可以从外往里找
'@': path.join(__dirname, './src/')
}
}
```
`outputPath`参数可以设置编译打包后图片的生成位置;
`limit`参数用于设置多大的图片需要转码为base64格式
`exclude`参数排除不需要转码的文件。
使用`babel`需要在项目根目录中添加一个`babel.config.js`配置文件,用于指定转换规则:
```javascript
// 向外导出一个 babel 的配置对象
module.exports = {
plugins:[
//以插件的形式,添加支持的转码规则,如下面的修饰器语法,class类语法
"@babel/plugin-proposal-decorators",
"@babel/plugin-proposal-class-properties"
]
}
```