webpack基础知识
一些问题
webpack 是什么?
是一种node一个第三方模块包, 用于打包代码
从本质上来讲,webpack是一个现在的javaScript应用的静态模块化打包工具。(从两点概括这句话即模块和打包)
当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
为什么要用webpack打包
如果不打包的话,我们的项目中有很多文件会相互依赖,有几个文件就要发多少次请求来获取文件,如果一个文件因为网络问题延误了整个页面也会延误,
而当我们的项目逐渐变大,有几十个到上百个JavaScript文件的时候,那问题会更严重。
不但有延迟问题,还会遇到很难维护的问题
而webpack就解决了这些问题,把所有JavaScript文件合成一个文件,
这样就减少了http请求数量,让我们的页面加载和显示更快。
不过这个合并的阶段是在开发完成之后才进行的,也就是说开发阶段我仍然是有a.js,b.js和c.js等等这些文件的,
这样才好开发和维护,因为如果开发阶段就合并的话,就相当于我基于一个可能上万行的文件进行开发,这样的代码是没法维护的。
when何时做
开发完成之后才进行 开发阶段我仍然是有a.js,b.js和c.js等等这些文件的,这样才好开发和维护
在开发后完成的这个合并的过程就是打包
how怎么做,如何提高效率,如何实施,方法是什么。
webpack在打包过程中,会分析各个文件之间的依赖关系,然后生成一个依赖图并用文件的形式保存下来,未来浏览器运行代码的时候就可以读取这个文件,就知道了各个代码块之间的关联以及如何调用了。
webpack 两大关键词 模块 打包
模块参考另一文章-模块化
好处:把很多文件打包整合到一起, 缩小项目体积, 提高加载速度
初始工作
初始化包环境
npm init
安装webpack包
cnpm i webpack webpack-cli -D
修改package.json, 自定义打包命令 - 让webpack使用配置文件
"scripts": {
"build": "webpack"
},
运行打包命令
cnpm run build
总结: src并列处, 生成默认dist目录和打包后默认main.js文件,默认会打包src下的index.js
webpack-入口和出口
入口和出口js文件可以手动配置,新建src并列处, webpack.config.js
// 默认入口: ./src/index.js
// 默认出口: ./dist/main.js
//可以手动配置webpack 入口、出口
// webpack配置 - webpack.config.js(默认)
// 新建src并列处, webpack.config.js
// 填入配置项
const path = require("path")
module.exports = {
entry: "./src/enrty.js", // 入口
output: {
path: path.join(__dirname, "dist"), // 出口路径
filename: "bundle.js" // 出口文件名
}
}
入口文件需要手动新建,引入依赖。出口文件是运行打包命令后自动生成的
没有在目录新建入口文件,只是配置了路径 时,报错:/home/zhq/webpack_test_project/src/entry.js doesn’t exist ,说明指定入口文件,需要在项目目录中对应路径新建该入口文件
入口文件里引入项目所需要的.js,.css文件,入口,出口文件是对应的,
以下是dist/index.html文件
bundle.js 配置的出口文件
打包后的html页面,只会加载出口文件的代码,非出口.js文件不管,如index.js,这里之前是模拟webpack打包写的,实际写页面时,不需要引入.js文件了,在配置入口时,相当于在引入js文件
<!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 defer src="bundle.js"></script></head>
<body>
<div>轮播图</div>
<div>tabs标签页</div>
</body>
<script src="../src/index.js"></script>
</html>
index.js文件
console.log('实现index.js')
import './js/aa.js'
输出:
实现轮播banner图的业务逻辑
实现tabs标签页的逻辑
index.js文件不执行
webpack-dev-server webpack开发服务器
解决打包费时问题
解决问题: 起一个开发服务器, 在电脑内存中打包, 缓存一些已经打包过的内容, 只重新打包修改的文件, 最终运行加载在内存中给浏览器使用
安装插件命令: cnpm i webpack-dev-server -D
配置
scripts: {
"build": "webpack",
"serve": "webpack serve --port 8083 --open"
//这样写可以启动一个服务器,指定端口号,输入npm run serve 之后自动打开页面
}
html-webpack-plugin插件
让webpack打包后生成html文件并自动引入打包后的js
自动生成html文件,需要有一个入口html文件
webpack打包后生成html文件并自动引入打包出口的js
配置文件中写
const HtmlWebpackPlugin=require('html-webpack-plugin');
module.exports = {
plugins:[
//目标: html-webpack-plugin插件, 让webpack打包后生成html文件并自动引入打包后的js
new HtmlWebpackPlugin({//自定义打包的html模版
template:'./public/test.html',
filename:'index.html'//自定义打包输出的文件名字
})
],
}
加载器 - 处理css文件 style-loader css-loader
webpack默认只认识 js 文件和 json文件
目标: loaders加载器, 可让webpack处理其他类型的文件, 打包到js中
cnpm i style-loader css-loader -D
style-loader 把 CSS 插入到 DOM 中。
css-loader 让webpack能够识别 css 文件的内容并打包
配置
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
};
加载器 - 处理less文件
安装less-loader
cnpm i less less-loader -D
注意: webpack默认只认识 js 文件和 json文件
require语法
多入口
入口定义:
1.基本概念:入口起点(entry point)指示webpack应该使用哪个模块来作为构建它的内部依赖图的开始。当进入入口之后,weboack会找出有哪些模块和库是入口起点(直接或者间接)依赖的。
在配置入口的时候其实做了两件事情:
确定入口模块位置,告诉Webpack从哪里开始进行打包。
定义chunk name。如果工程只有一个入口,那么默认其chunk name为“main”;如果工程有多个入口,我们需要为每个入口定义chunk name,来作为该chunk的唯一标识。
字符串类型入口
entry: "./src/entry.js"
数组类型入口
数组类型入口其实数组里的js文件最后还是合并到一个文件bundle.js上
entry:['./src/test1.js','./src/entry.js']
对象型入口
- 如果想要定义多入口,则必须使用对象的形式。对象的属性名(key)是chunk name(入口名称),属性值(value)是入口路径。如
entry:{//定义多入口,对象的属性名(key)是chunk name,属性值(value)是入口路径
entry:'./src/entry.js',
test1:'./src/test1.js'
},
output: {
path: path.join(__dirname, "dist"), // 出口路径
filename: "bundle.js" // 出口文件名 ,打包成的文件 ,自动生成的?
},
打包时出错:
Error: Conflict: Multiple chunks emit assets to the same filename bundle.js (chunks entry and test1) 冲突:多个块将资产发送到相同的文件名
问题原因:多文件入口,只指定了一个输出文件名
解决方案:每个需要打包的文件根据文件名打包输出
output: {
filename: './js/[name].js',
path: resolve(__dirname, 'build')
}
资源出口配置的参数大部分都在output里面
filename
filename是控制输出资源的文件名,是字符串形式
output: {
path: path.join(__dirname, "dist"), // 出口路径
filename: "bundle.js" // 出口文件名 ,打包成的文件 ,自动生成的?
},
filename不仅可以是文件名,也可以是路径,如下:
在多入口的场景中,如果需要为对应产生的每个bundle指定不同的名字,Webpack支持使用一种类似模板语言的形式动态地生成文件名,如:
context: path.join(__dirname, './src'),
entry: {
index: './index.js', //chunk name 为index
index2: './index2.js' //chunk name 为index2
},
output: {
filename: '[name].js' //name就是上面entry中的chunk name
},
结果:在dist目录下生成两个文件entry.js、 test1.js
多html页面出口
依赖插件 html-webpack-plugin
该插件将为你生成一个 HTML5 文件, 在 body 中使用 script
标签引入你所有 webpack 生成的 bundle。 只需添加该插件到你的 webpack 配置中,如下所示:
多入口已经完成了,但是打包后都插入到默认的index.html当中了, 因为只有一个出口,如何制作多出口,多出口肯定不止一个 模板文件,在index.html的同级目录新建一个出口文件为 about.html
单出口配置
plugins:[
//目标: html-webpack-plugin插件, 让webpack打包后生成html文件并自动引入打包后的js
new HtmlWebpackPlugin({//自定义打包的html模版
template:'./public/index.html',
filename:'index.html'//自定义打包输出的文件名字
}),
new CleanWebpackPlugin(), //通过new去执行.作用:清空输出的目录
],
这里多出口配置
module.exports = {
...
entry:{
index:'./src/index.js',
about:'./src/about.js'
},//
output: {
path: path.join(__dirname, "dist"), // 出口路径,在Webpack 4之后,output.path已经默认为dist目录,除非我们需要更改它,否则不必单独配置。
filename: '[name].js' //打包出口文件名 key.js
},
plugins:[
//目标: html-webpack-plugin插件, 让webpack打包后生成html文件并自动引入打包后的js
new HtmlWebpackPlugin({//自定义打包的html模版
template:'./public/index.html',
filename:'index.html',//自定义打包输出的文件名字
chunks:['index'] //代表指定的入口文件是哪个
}),
new HtmlWebpackPlugin({//自定义打包的html模版
template:'./public/about.html',//设置打包入口html文件是哪个
filename:'about.html',//自定义打包输出的文件名字
chunks:['about'] //代表指定的入口文件是哪个
}),
],
...
}
如果有较多的html出口,则plugins new HtmlWebpackPlugin会有多个, 代码会过于繁琐,可写成通用方法返回HtmlWebpackPlugin 实例,并以es6数组扩展符的形式,写入配置
let chunk_arr=['index','about'];//入口key数组
let html_plugin=chunk_arr.map(function(chunkName,index,self){//这是通用的返回
return new HtmlWebpackPlugin({ //自定义打包的html模版
template: `./public/${chunkName}.html`, //设置打包入口html文件是哪个
filename: `${chunkName}.html`, //自定义打包输出的文件名字
chunks: [chunkName] //代表指定的入口文件是哪个
})
})
module.exports = {
entry:{
index:'./src/index.js',
about:'./src/about.js'
},//
output: {
path: path.join(__dirname, "dist"), // 出口路径,在Webpack 4之后,output.path已经默认为dist目录,除非我们需要更改它,否则不必单独配置。
filename: '[name].js' //打包出口文件名 key.js
},
plugins:[
...html_plugin,//... 扩展运算符,可以将一个数组转为用逗号分隔的参数序列。
],
补充
一些心得体会
没有 run build,直接run serve,即webpack-dev-server 不能生成出口文件,因为webpack-dev-server负责的是在电脑内存中打包, 缓存一些已经打包过的内容
当我改了chunk name时,运行npm run serve 发现index.html文件中没有改动 ,webpack-dev-server是修改已缓存的打包内容,没有重新生成,何来修改?
如新增,删除文件时,要用npm run build命令,重新打包才行
现在有个问题,多次修改入口文件名时,会生成很多打包后的文件,且无用的文件不会自动清理,想清空一次输出目录,再重新生成新打包目录,怎么办?
答案:可以用一个插件 clean-webpack-plugin clean-webpack-plugin是一个Webpack插件,用于在每次构建前清理输出目录。它可以确保每次构建都是从一个干净的状态开始的,避免旧文件的干扰。
但使用后 webpack-dev-server就无效了,不能缓存
没有 run build,直接run serve,即webpack-dev-server 不能生成出口文件,因为webpack-dev-server负责的是在电脑内存中打包, 缓存一些已经打包过的内容
关于npm init解释
在node开发中使用npm init会生成一个pakeage.json文件,这个文件主要是用来记录这个项目的详细信息的,它会将我们在项目开发中所要用到的包,以及项目的详细信息等记录在这个项目中。方便在以后的版本迭代和项目移植的时候会更加的方便。也是防止在后期的项目维护中误删除了一个包导致的项目不能够正常运行。使用npm init初始化项目还有一个好处就是在进行项目传递的时候不需要将项目依赖包一起发送给对方,对方在接受到你的项目之后再执行npm install就可以将项目依赖全部下载到项目里。话不多说我们就直接开始进行操作。
参考:
https://blog.csdn.net/qq_36360463/article/details/107017638
https://blog.csdn.net/weixin_46862327/article/details/125364534
https://blog.csdn.net/weixin_39162041/article/details/104429517