0%

webpack

webpack

前端项目工程化的具体解决方案

以列表隔行变色来演示具体使用:

  1. 新建项目空白目录,并运行npm init -y命令,初始化包管理配置文件package.json

  2. 新建src源代码目录

  3. 新建src -> index.html首页和src -> index.js脚本文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./index.js"></script>
</head>
<body>
<ul>
<li>这是第1个列表</li>
<li>这是第2个列表</li>
<li>这是第3个列表</li>
<li>这是第4个列表</li>
<li>这是第5个列表</li>
<li>这是第6个列表</li>
<li>这是第7个列表</li>
<li>这是第8个列表</li>
<li>这是第9个列表</li>
</ul>
</body>
</html>
1
2
3
4
5
6
7
8
// 使用es6 语法导入
import $ from 'jquery'
// 定义jquery的入口函数
$(function(){
// 3、实现奇偶行变色
$('li:add').css('background-color','red')
$('li:even').css('background-color','green')
})
  1. 初始化首页基本的结构

  2. 运行npm install jquery -S命令,安装jQuery

  3. 通过ES6模块化的方式导入jQuery,实现列表隔行变色效果

    直接运行html发现报错Uncaught SyntaxError: Cannot use import statement outside a module

    在终端运行命令,安装webpack相关的包

1
npm install [email protected] [email protected] -D

packages.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"name": "vue_study01_webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
// 开发全流程用到的包 安装时 命令加 -S --save的简写
"dependencies": {
"jquery": "^3.6.0"
},
// 仅开发时用到的包 安装时 命令加 -D --save-dev的简写
"devDependencies": {
"webpack": "^5.42.1",
"webpack-cli": "^4.7.2"
}
}

  1. 配置webpack

    在项目根目录中创建名为webpack.config.js的webpack配置文件,并初始化如下的基本配置

    1
    2
    3
    module.exports = {
    mode: 'development' //mode用来指定构建模式,可选值有development和 production(代码压缩)
    }

    在package.json的scripts节点下,新增dev脚本如下:

1
2
3
"scripts":{
"dev":"webpack" // script节点下的脚本,可以通过npm run 执行 例如npm run dev
}

在终端执行npm run dev启动webpack进行项目的打包与构建

此时项目根目录会生成dist/main.js文件,将html文件里的index.js替换成这个main.js即可

webpack中的默认约定

  1. 默认的打包入口文件为src/index.js

  2. 默认的输出文件路径为dist/main.js

  3. 可在webpack.config.js配置文件中,通过entry节点指定打包入口。通过output节点指定打包的出口

1
2
3
4
5
6
7
8
9
10
const path = require('path')

module.exports = {
mode: 'development', //mode用来指定构建模式,可选值有development和production
entry: path.join(__dirname, './src/index.js'),
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
}
}

webpack中的插件

通过安装和配置第三方插件,可以拓展webpack的能力,从而让webpack用起来更方便。最常用的webpack插件有如下两个

webpack-dev-server

  • 类似于node.js阶段用到的nodemon工具

  • 每当修改了源代码,webpack会自动进行项目的打包和构建

  • 安装

  • 配置

    • 修改packages.json中的scripts中的dev命令如下
1
2
3
"scripts": {
"dev": "webpack serve"
},
  • 再次运行npm run dev

  • 浏览器访问http://localhost:8080

  • 插件会将生成的js保存在内存中的项目根目录,此时还需将html中的 js文件引入路径改成 根目录下的boundle.js

html-webpack-plugin

  • webpack中的html插件(类似于一个模板引擎插件)

  • 可以通过此插件自定制index.html页面的内容

  • 安装

  • 配置

    • 修改webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin')


const htmlPlugin = new HtmlPlugin({
template: './src/index.html', //源文件存放路径
filename: './index.html' // 文件生成路径
})

module.exports = {
mode: 'development', //mode用来指定构建模式,可选值有development和production
entry: path.join(__dirname, './src/index.js'),
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
plugins: [htmlPlugin],
}

  • 说明

    • 通过插件复制到项目根目录下的index.html页面也是在内存中
    • 插件生成的html会自动注入打包的js文件(bundle.js)
  • devServer节点可指定本地启动服务的端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
mode: 'development', //mode用来指定构建模式,可选值有development和production
entry: path.join(__dirname, './src/index.js'),
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
plugins: [htmlPlugin],
devServer: {
open: true, // 自动打开浏览器
host: '127.0.0.1',
port: 8000,
}
}

webpack中的loader

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

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

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

打包处理css文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module.exports = {
mode: 'development', //mode用来指定构建模式,可选值有development和production
entry: path.join(__dirname, './src/index.js'),
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
plugins: [htmlPlugin],
devServer: {
open: true, // 自动打开浏览器
host: '127.0.0.1',
port: 8000,
},
module: {
rules:[
{ test: /\.css$/,use:['style-loader','css-loader']}
]
}
}
// test 表示匹配的文件类型,use表示对应要调用的loader
// use中指定的loader数组顺序是固定的,调用顺序是从后往前

打包处理less文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module.exports = {
mode: 'development', //mode用来指定构建模式,可选值有development和production
entry: path.join(__dirname, './src/index.js'),
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
plugins: [htmlPlugin],
devServer: {
open: true, // 自动打开浏览器
host: '127.0.0.1',
port: 8000,
},
module: {
rules:[
{ test: /\.css$/,use:['style-loader','css-loader']},
{ test: /\.less$/,use:['style-loader','css-loader','less-loader']}
]
}
}
// test 表示匹配的文件类型,use表示对应要调用的loader
// use中指定的loader数组顺序是固定的,调用顺序是从后往前

打包处理跟url相关的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module.exports = {
mode: 'development', //mode用来指定构建模式,可选值有development和production
entry: path.join(__dirname, './src/index.js'),
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
plugins: [htmlPlugin],
devServer: {
open: true, // 自动打开浏览器
host: '127.0.0.1',
port: 8000,
},
module: {
rules:[
{ test: /\.css$/,use:['style-loader','css-loader']},
{ test: /\.less$/,use:['style-loader','css-loader','less-loader']},
{ test: /\.jpg|png|gif$/,use:'url-loader?limit=22229'}
]
}
}
// ?后是指参数limit后指文件大小单位字节,只有<=limit的图片才会被转成base64

打包处理js高级语法

webpack 只能打包处理一部分高级的JavaScript 语法。对于那些webpack 无法处理的高级js 语法,需要借助于babel-loader进行打包处理。例如webpack无法处理下面的JavaScript代码:

1
2
3
4
5
6
7
function info(target){
target.info = 'i am mb';
}

@info
class Person {}
console.log(Person.info);
1
2
3
4
5
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/ // 排除项
}
  • 配置babel-loader

    • 在项目根目录创建babel.config.js
1
2
3
module.exports={
plugins: [['@babel/plugin-proposal-decorators', {legacy: true}]]
}
[^官方文档]: https://babeljs.io/docs/en/babel-plugin-proposal-decorators

配置打包发布

  • 在package.json文件的scripts节点下,新增build命令如下
1
2
3
4
5
6
"scripts": {
"dev": "webpack serve",
"build": "webpack --mode production"
},
// --mode是一个参数项,用来指定webpack的运行模式。production代表生产环境,会对打包生成的文件进行代码压缩和性能优化
// 通过--model指定的参数项,会覆盖webpack.config.js中的model选项
  • 把图片放到统一的images目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
test: /\.jpg|png|gif$/,
use: {
loader: 'url-loader',
options: {
limit: 22228,
outputPath: 'image'
}
}
},
// 或者
{
test: /\.jpg|png|gif$/,
use: 'url-loader?limit=22229&outputPath=images'
},
  • 自动清理dist目录下的旧文件
1
2
3
4
5
6
7
// 1.安装插件
npm i clean-webpack-plugin@3.0.0 -D

// webpack.config.js中配置
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const cleanPlugin = new CleanWebpackPlugin()
plugins: [htmlPlugin,cleanPlugin],

sourceMap

Source Map就是一个信息文件,里面储存着位置信息。也就是说,Source Map文件中存储着压缩混淆后的代码,所对应的转换前的位置。
有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码,能够极大的方便后期的调试。

开发环境下,推荐在webpack.config.js添加如下的配置,即可保证运行时报错的行数与源代码的行数

1
2
3
4
module.exports = {
mode: 'development',
devtool: 'eval-source-map', // 生产环境去掉或者改成nosources-source-map 只暴露行号不展示代码
}

webpack中的@

  • 引入文件时,可将@代表为src目录
1
2
3
import '../../../../msg'
// 替换为
import '@/test/00/01/msg'
  • 首先要配置webpack.config.js
1
2
3
4
5
6
7
module.exports = {
resolve: {
alias: {
'@': path.join(__dirname,'/src/')
},
},
}
赏口饭吃吧!