342 lines
11 KiB
Markdown
342 lines
11 KiB
Markdown
---
|
||
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
|
||
}
|
||
```
|
||
|
||

|
||
|
||

|
||
|
||
> `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标签中;
|
||
|
||

|
||
|
||
常用的`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"
|
||
]
|
||
}
|
||
```
|
||
|
||
|
||
|