webpack(10) webpack扩展(插件. loader)
webpack做的事情, 仅仅是分析各个模块间的依赖关系, 将chunk里的资源合并成资源列表, 然后输出打包文件;
更多的事情, 需要loader和plugin来完成;
plugin的用法, 通过npm来找用法
1. clean-webpack-plugin:
每次打包前清除配置文件中的输出包.
原理: 注册compiler.hooks的emit事件, 用fs模块删除配置文件的目录;
注意: 经过我测试, 和多文件应用时候, 必须配置filename属性, 否则clean-webpack-plugin会因为文件名相同而不起作用
2. HTML Webpack Plugin
将打包生成的js文件放到html文件中, 然后输出;可以只生成一个html文件, 也可以指定固定的/ 多个模板html
多页面设置: 使用多次 new HtmlWebpackPlugin({chunks:[]})
1 module.exports = (env)=>{ 2 return { 3 mode: env.prod ? "production" : "development", 4 devtool: env.prod ? "eval" : "source-map", 5 plugins:[ 6 new HtmlWebpackPlugin({ 7 title: "My App", 8 filename:"index.html", 9 template:"./src/assets/index.html", //指定生成模板 10 chunks: ['index'] //根据入口中定义的chunks的值生成不同的script标签, 默认是all; 11 }), 12 new HtmlWebpackPlugin({ 13 title: "abc", 14 filename:"abc.html",//这个必须有 15 template:"./src/assets/abc.html", 16 chunks: ['abc'] 17 }), 18 new CleanWebpackPlugin(), 19 ], 20 21 entry:{ 22 index:"./src/index.js", 23 abc:"./src/abc.js" 24 },
原理: 检查有没有template属性, 有就读取文件, 抽象语法树分析文件,没有就生成一个空的html文件.
检查是否有chunks的属性, 有就将第一步的文件以script标签的形式输出chunkfs选项的代码 ,生成页面文件输出
3. copy-webpack-plugin
作用: 将已存在的静态文件, 单独的,或者全部目录, copy到输出目录中. 即在用到html-webpack-plugin时, 如果html模板文件中有静态文件引入标签, 比如<img src="./img/a.jpg">,则会导致输出的文件中, 找不到img的src,必须将html对应的静态文件打包输出, 这也就是为什么html-webpack-plugin和copy-webpack-plugin一般都同时用的原因.
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
}),
原理, 会根据配置读取copy的目录或文件, 然后打包后输出
4. dev-server 开发时用的服务器;
注意, 该命令是webpack官方出的(文档不在npm上, 在webpack上).能够自动生成一个临时服务器,解决了
- 频繁npx webpack命令的问题,
- 开发过程中生成的页面在服务器上模拟真实的环境.
用法: 按装: npm install webpack-dev-server --save-dev
启动命令: npx webpack serve
webpack server做的操作:
- 传递命令行参数,
- 开启watch监听,
- 注册钩子函数, 保存资源列表, 禁止webpack输出文件,
- 开启express服务器, 监听端口, 根据浏览器的请求,返回资源.
webpack-dev-server最常用的配置就是代理服务器, 来解决跨域问题:
情景: 1. 开发时候, 用的localhost:8080端口的服务器环境,因为需要用--watch功能和在服务器上的功能, 比如, 发送ajax请求, 单纯的浏览器上时无法办到的,
2 但请求的服务器是后端的, 或者localhost:9000端口, 不管域名还是端口不一致, 就造成了跨域问题,
3. proxy正是解决这个问题的:https://webpack.docschina.org/configuration/dev-server/#devserverport
module.exports = (env) => { return { mode: env.prod ? "production" : "development", devtool: env.prod ? "eval" : "source-map", ... devServer: { open: true, port: 8080, proxy: { //含义是: 属性名是正则表达式/\/api/, 如果能匹配, 则将本次请求的协议域名端口换成属性值; //即原本的http://127.0.0.1:8080/api/abc被换成了http://127.0.0.1:3000/api/abc "/api": "http://127.0.0.1:3000",
"changeOrigin
": true //是否转换请求头信息, 针对 有些服务器会对非本服务器的请求作出限制 的请求;
}, }, }
proxy的配置需要注意的几点:
1.如果不希望传递/api
,则需要重写路径:
1 webpack.config.js 2 3 module.exports = { 4 //... 5 devServer: { 6 proxy: { 7 '/api': { 8 target: 'http://localhost:3000', 9 pathRewrite: { '^/api': '' }, //把匹配到的这个内容, 替换成空串 10 }, 11 }, 12 }, 13 };
2,代理时会保留主机头的来源,可以将 changeOrigin
设置为 true
以覆盖此行为
6. file-loader和url-loader的配合使用
6.1 file-loader
情景: 当用require方式引入静态文件, 会导致抽象语法树无法解析图片的数据,
原因就是在引入.jpg文件后, 抽象语法树不能解析这种二进制数据, 需要loader来帮着转换.
作用: (1)将require("文件路径")这种导入的文件, 作为src地址导出,
(2) 将导入的文件导出到输出目录
原理: function file-loader(source){ //source是文件内容(图片内容的buffer)
// 1.生成具有相同内容的文件到输出目录
// 2. 返回一段代码 export default "文件名"
}
//index.js import imgSrc from './assets/img/1.png';// 说明file-loader内部是export default "文件路径"
注意点:
- 这个file-loader是在打包过程中用的, 而不是打包后用到的, 所以应该用npm i -D安装;
- loader和plugin是不一样的, loader是不需要引入的, 可以直接使用; 这是因为loader的配置规则写法和plugin是不一样的,
plugins的配置是一个数组, 直接new xxplugin, 所以得提前引入, 而loader用modlue:...user: [xxloader]这种写法, 相当于 用了require了,会找node_module目录下寻找xxloader,然后导入
module.exports = (env) => { return { mode: env.prod ? "production" : "development", devtool: env.prod ? "eval" : "source-map", module: { noParse: /jquery|lodash/, rules: [ { test: /\.(png|jpe?g|gif)$/i, loader: 'file-loader',//只用一个loader可以直接写,而不需要写use options: { outputPath: 'images',//也可以写"/images" name: '[name]_[hash:5].[ext]'//hash是fileloader生成的. }, }, ], },
6.2 url-loader:
url-loader
works like file-loader
, but can return a DataURL if the file is smaller than a byte limit.
file-load是生成一个文件到输出目录, 并将模块文件设置成导出路径;
url-loader是将依赖文件转换成为:导出base64格式的字符串;
url-loader原理:
function url-loader(source){ //source是文件内容(图片内容的buffer)
// 1.将buffer生成一个base64编码
// 2. 返回一段代码 export default "base64编码"
}
url-loader配置注意: urlloader配置完后, 不能单独再配置一个file-loader, 就可以使用
A Number
or String
specifying the maximum size of a file in bytes. If the file size is equal or greater than the limit file-loader
will be used (by default) and all query parameters are passed to it.
module.exports = (env) => {
return {
mode: env.prod ? "production" : "development",
devtool: env.prod ? "eval" : "source-map",
module: {
noParse: /jquery|lodash/,
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 100 * 1024,//只要文件不超过100kb,则使用base64,否则用file-loader
//注意, 配置了url-loader后就不能再去单独配置file-loader了,否则会全部使用file-loader
//下面的配置会自动传递给file-loader
outputPath: 'images',
name: '[name]_[hash:5].[ext]'
},
},
url-loader的作用是: 当文件很小,且数量比较大时候, 如果都用file-loader, 会增加网络请求数量, 这是以文件的体积换取网络请求的数量的
7. output.publicpath对webpack生成的文件的路径影响;
1. 将webpack.config.js中的output.publicPath设置为一个字符串;
2. 从webpack生成的index.js的源码中可以看出
2.1 源码中定义了一个公共路径
2.2 在导出图片时候, 导出的内容是output.publicPath + require的参数,
2.3这样打包形成的所有文件, 都会加上publicPath, 比如经过插件HtmlWebpackPlugin形成的html文件, 它的形成的标签都是加入output.publicPath的;
这样形成的文件, 打包出来会对路径造成严重影响,
所以, 我们一般配置为打包的网站内容:"/",原因是:
"/xx"是绝对路径, 会自动请求网站下的路径资源(省略了协议域名端口),如网站是http:www.abc.com; 这样就会自动请求http:www.abc.com/xx
所有成熟的loader和插件对导出路径都会受到output.publicpath的影响.
8 .webpack内部插件
用法: 在配置文件中,
//webpack.config.js const webpack = require('webpack'); module.exports = { plugins:[ new webpack.BannerPlugin({ banner: 'hello world', }),
new webpack.ProvidePlugin({ //引入常用的库
...
]
}
1.BannerPlugin : 为每个chunk添加头信息 Add a banner to the top of each generated chunk
\2. ProvidePlugin: 在全局定义常用库