什么是webpack
webpack是前端工程化的具体解决方案。
主要功能:提供了友好的前端模块化开发支持,以及代码压缩混淆、处理浏览器端javaScript的兼容性、性能优化等强大的功能
快速使用 webpack
新建项目空目录,运行 npm init -y 命令,初始化包管理配置文件 package.json
新建src源码目录
新建src-index.html 首页文件 和 src->index.js脚本文件
初始化首页基本的结构
运行npm install jquery -S 安装 jQuery 这个命令执行后,会把这个包和对应的版本记录到 package.json
中的 dependencies
节点下
在上面的五个步骤结束后,会产生下面这样的目录结构
1 2 3 4 5 6 7
| - quickwebpack |- node_modules |- src |- index.js |- index.html |- package-lock.json |- package.json
|
我们在 index.html
和 index.js
中写一些代码,使用ES6高级语法,去尝试一下webpack
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <!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> <img src="" alt="" class="box"> </body> </html>
|
1 2 3 4 5 6 7 8 9 10
| import $ from 'jquery'
$(function(){ $('li:odd').css('background-color','red') $('li:even').css('background-color','yellow') })
|
直接用浏览器打开,运行报错,因为ES6的import高级语法不兼容
下面需要使用webpack来解决它
1. 安装:
1
| npm install webpack@5.42.1 webpack-cli@4.9.1 -D
|
运行上面的命令后,在 package.json
中 devDependencies
记录这两个包 devDependencies
中的包只在开发中有用
2. 配置:
在项目根目录中,创建名为 webpack.config.js
的 webpack 配置文件,并初始化如下配置
1 2 3
| module.exports = { mode:"development" }
|
在 package.json
的scripts
节点下,新增dev脚本如下:
script 节点下的脚本,通过npm run
执行,比如 npm run dev
注意不要在 package.json
中写注释
1 2 3
| "scripts":{ "dev":"webpack" }
|
在终端执行 npm run dev
进行打包
打包后,会在项目根目录下生成一个dist文件夹,在dist文件夹下生成一个 main.js
,此时的目录结构如下
1 2 3 4 5 6 7 8 9 10
| - quickwebpack |- dist |- main.js |- node_modules |- src |- index.js |- index.html |- package-lock.json |- package.json |- webpack.config.js
|
我们在 index.html
中引入 main.js
1
| <script src="../dist/main.js"></script>
|
此时再用浏览器打开,就可以看到隔行变色的效果了
webpack.config.js 的配置文件中,module 的 production模式会有代码压缩效果,生成时间长,但是代码体积小
webpack 4.x和5.x默认的打包入口文件为 src->index.js
默认的输出文件路径为 dist-> main.js
修改 webpack.config.js
中打包的默认约定,将下面的代码写入 webpack.config.js
进行输入输出文件的修改,这样输出的文件就会命名为 index1.js
,记得改完生成文件的路径和名称后要去html代码中修改引入的路径
1 2 3 4 5 6 7 8 9 10 11 12 13
| const path = require('path') module.exports = { mode:'development', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' } }
|
webpack的插件
在体会了webpack的使用后,我们还需要了解一些让webpack用起来更加方便的插件
webpack-dev-server
每次我们修改完代码,想要在浏览器中产看效果前,都需要进行打包,很不方便
这个插件就是达到一个每当修改了源代码,就会自动进行项目打包的目的
安装
执行下面的命令后,将 webpack-dev-server
安装在 devDependencies
节点下
1
| npm install webpack-dev-server@3.11.2 -D
|
配置
修改 package.json->scripts
中的dev命令:
1 2 3
| "scripts": { "dev": "webpack server" },
|
再次运行npm run dev 命令进行项目打包
在浏览器访问http://localhost:8080 可以看到我们根目录的一个文件结构,进入src目录下,就可以看到html页面的效果了
现在我们修改js代码,会发现页面并没有自动同步变化,仔细阅读控制台提示
发现插件把生成的文件放在根目录中,但是我们在文件夹中却也看不到,其实这个插件是把生成的文件放在了内存中,在浏览器访问 http://localhost:8080/index1.js
就可以看到 (这里是因为我之前把输出文件的名字改成了 index1.js
)
所以想要看到最新效果,就要在html中引入根目录下的 index1.js
(这个文件在文件夹中看不到,它在内存中,引入的代码如下所示) ,再次保存刷新,就可以在浏览器看到修改后的效果了。
1 2
| <script src="../index1.js"></script>
|
webpack-dev-plugin
我们打包完成后,还需要进入 src
目录下才可以看到页面,使用这个插件可以将页面复制一份,放在根目录中
安装
运行下面的命令进行插件安装
1
| npm install html-webpack-plugin -D
|
配置
在 webpack.config.js
中进行配置
导入插件,得到一个构造函数
1 2
| const HtmlPlugin = require('html-webpack-plugin')
|
创建 HTML 插件的实例对象
1 2 3 4 5 6 7
| const htmlPlugin = new HtmlPlugin({ template:'./src/index.html', filename:'./index.html' })
|
把实例对象挂在plugins下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| module.exports = { mode:'development', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' }, plugins:[htmlPlugin] }
|
这个插件复制的文件也是在内存中的,并且还会自动在文件中注入生成的js
文件,我们就不用手动修改引用的js文件的路径了
旧的 webpack.config.js |
修改后的 webpack.config.js |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const path = require('path') module.exports = { mode:'development', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' } }
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' }, plugins:[htmlPlugin] }
|
|
devserver节点
在webpack.config.js
配置文件中,可以通过 devServer
节点对webpack-dev-server
插件进行更多的配置
配置每次打包完成后自动打开页面,这样我们就不需要手动去打开页面了
对webpack 的节点操作,都是在 webpack.config.js
的 module.explort
里
1 2 3 4 5
| devServer:{ open:true,//初次打包完后,自动打开浏览器 host:'127.0.0.1',//实时打包使用的主机地址 port:8080,// 实时打包使用的端口号 }
|
注意:凡是修改了webpack.config.js
配置文件,或者修改了package.json
配置文件,必须重新启动打包的服务
旧的 webpack.config.js |
修改后的 webpack.config.js |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' }, plugins:[htmlPlugin] }
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' }, plugins:[htmlPlugin], devServer:{ open:true, host:'127.0.0.1', port:8080, } }
|
|
webpack 中的 loader
loader概述
在实际开发中,webpack默认只能打包处理.js 后缀结尾的模块,其他非.js 结尾的模块,webpack默认处理不了,需要调用loader加载器才可以正常打包,否则会报错
loader加载器的作用:协助webpack 打包处理待定的文件模块。比如:
- css-loader 可以打包.css文件
- less-loader 可以打包.less文件
- babel-loader 可以打包处理webpack无法处理的高级js语法
打包处理css文件
安装
使用下面的命令安装需要的插件
1
| npm i style-loader@3.0.0 css-loader@5.2.6 -D
|
配置
在 webpack.config.js
中的 module->rules
数组中,添加loader规则如下
1 2 3 4 5 6
| module:{ rules:[ {test:/\.css/,use:['style-loader','css-loader']} ] }
|
打包处理less文件
安装
使用下面的命令安装需要的插件
1
| npm i less-loader@10.0.1 less@4.1.1 -D
|
配置
在 webpack.config.js
的 module->rules
数组中,添加loader规则如下
1 2 3 4 5
| module:{ rules:[ {test:/\.less/,use:['style-loader','css-loader','less-loader']} ] }
|
打包处理样式表中与url路径相关的文件
安装
使用下面的命令安装需要的插件
1
| npm i url-loader file-loader -D
|
配置
在 webpack.config.js
的 module->rules
数组中,添加loader规则如下
1 2 3 4 5
| module:{ rules:[ {test:/\.jpg|png|gif$/,use:'url-loader?limit=22229'}, ] }
|
? 后面是loader的参数,limit用来指定图片大小,单位字节,只有小于等于limit大小的图片,才会被转成base64格式的图片
5. 打包处理js高级语法
安装
使用下面的命令安装 babel-loader
相关的包
1
| npm i babel-loader@8.2.2 @babel/core@7.14.6 @babel/plugin-proposal-decorators@7.14.5 @babel/preset-env @babel/plugin-transform-runtime-D
|
配置
在 webpack.config.js
的 module->rules
数组中,添加loader规则如下
1
| {test:/\.js$/,use:'babel-loader',exclude:/node_modules/}
|
exclude 用来排除第三方包中的js文件
使用 babel-loader
的时候,需要定义Babel的配置项
在项目根目录下创建一个 babel.config.js
的配置文件内容如下:
1 2 3 4
| module.exports = { plugins:[['@bable/plugin-proposal-decorators',{legacy:true}]] }
|
如果这些 loader 都配置完后,webpack.config.js
可能就变成了下面的样子
旧的 webpack.config.js |
修改后的 webpack.config.js |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' }, plugins:[htmlPlugin], devServer:{ open:true, host:'127.0.0.1', port:8080, } }
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 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', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' }, plugins:[htmlPlugin], devServer:{ open:true, host:'127.0.0.1', port:8080, }, 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'}, {test:/\.js$/,use:'babel-loader',exclude:/node_modules/} ] }, }
|
|
我们可以在 src
下面新建 css
文件夹,和 image
文件夹 放入对应文件图片,并使用 ES6 语法引入后打包查看效果
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <!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="./index1.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> <img src="" alt="" class="box"> </body> </html>
|
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 24 25 26 27
| import $ from 'jquery'
import './css/index.css' import './css/index.less'
import logo from './images/logol.png'
$('.box').attr('src',logo)
$(function(){ $('li:odd').css('background-color','red') $('li:even').css('background-color','yellow') })
function info(target){ target.info = 'Person info' }
@info class Person { }
console.log(Person.info)
|
webpack的打包发布
前面都是生产环境中打包测试,自己查看效果,当项目做完后,我们就需要进行打包发布,这个时候,我们还需要一些额外的配置
基本使用
在 package.json
文件的 scripts
节点下面新增build命令
1 2 3 4
| "scripts": { "dev": "webpack server", "build":"webpack --mode production" },
|
--mode
是一个参数,用来指定webpack 的运行模式,production代表生产环境,这里 --modle
指定的运行模式会覆盖 webpack.config.js
中的定义
在命令行运行 npm run build就好了
把生成的包各类文件,放在同一个文件夹
为了让文件生成后不是挤在一个文件夹中,我们可以分别在 webpack.config.js
文件中修改下面两个地方,来让文件放在不同的文件夹中
1 2 3 4 5 6
| output:{ path:path.join(__dirname,'./dist'), filename:'js/index1.js' },
|
1 2
| {test:/\.jpg|png|gif$/,use:'url-loader?limit=22229&outputPath=images'},
|
3. 自动删除上次生成的文件
为了防止之前生成的文件干扰我们我们需要安装 clean-webpack-plugin
插件
安装
使用下面的命令进行安装
1
| npm install clean-webpack-plugin -D
|
配置
在 webpack.config.js
文件和 plugins
节点数组中增加下面的代码
1 2 3 4 5 6 7
| const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = { plugins: [ new CleanWebpackPlugin() ], };
|
Source Map
Source Map
是一个信息文件,里面存储着位置信息,存着压缩后的代码的行号和原来的行号
默认报错显示压缩后的行号,调试不方便,改一下配置
在 webpack.config.js
中添加如下配置,保证运行时报错的行号和源代码的一样
1 2 3 4 5 6
| module.exports = { mode:'development', devtool:'eval-source-map' }
|
旧的 webpack.config.js |
修改后的 webpack.config.js |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' }, plugins:[htmlPlugin], devServer:{ open:true, host:'127.0.0.1', port:8080, }, 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'}, {test:/\.js$/,use:'babel-loader',exclude:/node_modules/} ] }, }
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| const path = require('path') const HtmlPlugin = require('html-webpack-plugin') const htmlPlugin = new HtmlPlugin({ template:'./src/index.html', filename:'./index.html' })
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { mode:'development', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'index1.js' }, devtool:'eval-source-map', plugins:[htmlPlugin,new CleanWebpackPlugin(),], devServer:{ open:true, host:'127.0.0.1', port:8080, }, 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'}, {test:/\.js$/,use:'babel-loader',exclude:/node_modules/} ] }, }
|
|
improt路径优化
我们的代码在src
文件夹中,每次引入文件和代码的时候,都需要使用 ../
来进行路径查找,这样从内往外查找很不清楚,我们使用下面的配置,来优化路径查找方式
在 webpack.config.js
节点中添加 resolve
节点
1 2 3 4 5 6
| resolve:{ alias:{ '@':path.join(__dirname,'./src/') } }
|
通过所有的配置,我们最后的项目结构如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| - quickwebpack |- dist |- main.js |- node_modules |- src |- css |- index.css |- index.less |- images |- logol.png |- index.js |- index.html |- package-lock.json |- package.json |- webpack.config.js |- bable.config.js
|
webpack.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlPlugin({ template:'./src/index.html', filename:'./index.html' })
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = { mode:'development', entry:path.join(__dirname,'./src/index.js'), output:{ path:path.join(__dirname,'./dist'), filename:'js/index1.js' }, devtool:'eval-source-map', plugins:[htmlPlugin,new CleanWebpackPlugin(),], devServer:{ open:true, host:'127.0.0.1', port:8080, }, 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&outputPath=images'}, { test:/\.js$/, exclude:/node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], plugins: [ ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose" : true }], ["@babel/plugin-transform-runtime"] ] } } } ] }, resolve:{ alias:{ '@':path.join(__dirname,'./src/') } } }
|
写在最后
事实上,我们一般不用自己配置webpack , 学习webpack是为了可以大概看懂配置,以防出现奇起怪怪的错误