webpack4之路(3)-Plugins
tips:上一篇我们已经一起学习了webpack的loader配置,现在我们来学webpack的重要功能Plugins(插件)吧~~
什么是插件?
插件(Plugins)是用来拓展webpack功能的,它们会在整个构建过程中生效,执行相关任务。插件的目的在于解决loader无法实现的其他事。
插件与loader的区别
Loaders是打包构建过程中用来处理源文件如(JSX,Scss,Less...)一次处理一个;插件并不是直接操作单个文件,它直接对整个构建过程起作用。
插件的使用
使用插件,首先要用npm进行安装,然后在webpack.config.js配置文件的plugins(是一个数组)配置中添加该插件的实例。先从简单的版权声明插件开始
webpack.config.js
const path = require('path') const webpack = require('webpack') // 版权声明插件不用安装,是基于webpack,所以只要引入webpack即可 module.exports = { mode: 'development', entry: { index: './scripts/index.js' // 入口文件,若不配置webpack4将自动查找src目录下的index.js文件 }, output: { filename: '[name].bundle.js', // 输出文件名,[name]表示入口文件js名 path: path.join(__dirname, 'dist') // 输出文件路径 }, devServer: { host: 'localhost', // 主机地址 compress: true, // 开发服务器是否启动gzip等压缩 contentBase: './dist',//开发服务运行时的文件根目录 inline: true, port: 9000 // 监听的端口 }, module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.(scss|sass)$/, // 正则匹配以.scss或者.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.js|\.jsx$/, loader: "babel-loader", exclude: /node_modules/ // 不包括依赖内的js文件 } ] }, plugins: [ new webpack.BannerPlugin('版权所有,翻版必究') // new一个插件实例 ] }
运行npm run server. 我们就可以在打包出来的文件里查看
提前预热完成,现在开始进入主题啦~~~
1.htmlWebpackPlugin
看名字就知道这是处理关于HTML的。这个插件简化了HTML的创建.它的主要两个作用分别是1.为html文件中引入的外部资源如script、link动态添加每次compile后的hash, 防止引用缓存的外部文件问题2.可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置N个html-webpack-plugin可以生成N个页面入口。
原理:
将 webpack中`entry`配置的相关入口chunk 和 `extract-text-webpack-plugin`抽取的css样式 插入到该插件提供的`template`或者`templateContent`配置项指定的内容基础上生成一个html文件,具体插入方式是将样式`link`插入到`head`元素中,`script`插入到`head`或者`body`中。
安装:
npm i html-webpack-plugin -D
然后我们要去项目结构进行一些更改,把dist整个文件夹删除;
然后就开始配置webpack.config.js
const path = require('path') const webpack = require('webpack') // 版权声明插件不用安装,是基于webpack,所以只要引入webpack即可 const HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件 module.exports = { mode: 'development', entry: { index: './scripts/index.js' // 入口文件,若不配置webpack4将自动查找src目录下的index.js文件 }, output: { filename: '[name].bundle.js', // 输出文件名,[name]表示入口文件js名 path: path.join(__dirname, './dist') // 输出文件路径 }, devServer: { host: 'localhost', // 主机地址 compress: true, // 开发服务器是否启动gzip等压缩 contentBase: './dist',//开发服务运行时的文件根目录 historyApiFallback: true, // 不跳转 inline: true, port: 9000 // 监听的端口 }, stats: { entrypoints: false, children: false }, module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.(scss|sass)$/, // 正则匹配以.scss或者.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.js|\.jsx$/, loader: "babel-loader", exclude: /node_modules/ // 不包括依赖内的js文件 } ] }, plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件实例 new HtmlWebpackPlugin({ title: 'Hello Webpack', }) ] }
这里主要就是引入了HtmlWebpackPlugin插件,并做了修改标题操作。之前在package.json里是没有配置打包脚本的,为了方便先配置个脚本。
"build": "webpack"
执行npm run build之后 你会 发现一个新的dist包。里面就是你打包出来的内容了。这样代表成功了哦
到这里。不知道 有没有宝宝和我一样有一个疑惑,我本地也没有index.html的入口,只有一个js文件。那我监听的9000端口html在哪。这个疑问真是让我想了好久好久,最终和同事聊起才知道,它会看有没有有设置默认的入口,如果没有的话会给你建个缓存的html.
为了验证,那我就在根目录下建个index.html文件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello Webpack</title> </head> <body> new html </body> </html>
然后我们还要在webpack.config.js引入HtmlWebpackPlugin插件的地方进入简单的配置
plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件实例 new HtmlWebpackPlugin({ title: 'Hello Webpack', template: path.join(__dirname, 'index.html') }) ]
现在运行npm run server就可以看到效果了
这样就有你监听的html了,如果你要改什么html就可以在这里改。优秀。
2.ExtractTextWebpackPlugin(抽离css样式)
npm install --save-dev mini-css-extract-plugin
在webpack.config.js配置
const path = require('path') const webpack = require('webpack') // 版权声明插件不用安装,是基于webpack,所以只要引入webpack即可 const HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件 const miniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { mode: 'development', entry: { index: './scripts/index.js' // 入口文件,若不配置webpack4将自动查找src目录下的index.js文件 }, output: { filename: '[name].bundle.js', // 输出文件名,[name]表示入口文件js名 path: path.join(__dirname, './dist') // 输出文件路径 }, devServer: { host: 'localhost', // 主机地址 compress: true, // 开发服务器是否启动gzip等压缩 contentBase: './dist',//开发服务运行时的文件根目录 historyApiFallback: true, // 不跳转 inline: true, port: 9000 // 监听的端口 }, stats: { entrypoints: false, children: false }, module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 // use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 use: [ miniCssExtractPlugin.loader, { loader: 'css-loader', options: { url: false } } ] }, { test: /\.(scss|sass)$/, // 正则匹配以.scss或者.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.js|\.jsx$/, loader: "babel-loader", exclude: /node_modules/ // 不包括依赖内的js文件 }, ] }, plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件实例 new HtmlWebpackPlugin({ title: 'Hello Webpack', template: path.join(__dirname, 'index.html') }), new miniCssExtractPlugin({ filename: 'index.css' }) ] }
修改的地方分别是引入,rule与plugins插件实例。运行npm run webpack就可以看到打出来的css文件了。
3.cleanWebpackPlugin
当我们每次打包完文件后,都会生成一个新的dist文件覆盖上一个dist文件,但如果上个dist的一 些其他文件没有被覆盖,他就会一直存在那里,随着打包次数的增多,这种无用而可能会影响我们的代码越来越多,会严重影响我们的性能。
cleanWebpackPlugin插件做的就是每次打包时都会删除上一次打包的文件,而不是覆盖。这样每次都是全新的包了。
npm i clean-webpack-plugin -D
配置webpack.config.js
const CleanWebpackPlugin = require('clean-webpack-plugin') // 引入插件 plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件实例 new HtmlWebpackPlugin({ title: 'Hello Webpack', template: path.join(__dirname, 'index.html') }), new miniCssExtractPlugin({ filename: 'index.css' }), new CleanWebpackPlugin() ]
运行,npm run build.报错了
报错说,CleanWebpackPlugin不是一个构造函数。于是查阅资料知道由于clean-webpack-plugin.d.ts.文件中它是以一个对象属性的形式导出,所以我们引入的时候需要以解构方式来获取,所以我们修改引入方式
const { CleanWebpackPlugin }= require('clean-webpack-plugin')
再次执行打包命令就正常了,而且没有冗余的文件了。
4.HotModuleReplacementPlugin(热更新)
HotModuleReplacementPlugin(HMR)可以在我们修改代码后自动刷新预览效果。
说一个我遇到的疑问吧,因为我之前是有在devServer下配置inline:ture所以每次我修改并保存后页面的东西就会变化,我就想着说这和热加载有什么区别:
// 1. 不会刷新浏览器 $ npm run server//2. 刷新浏览器 $ npm run server --inline //3. 重新加载改变的部分,不会刷新页面 $ npm run server --hot //4. 重新加载改变的部分,HRM失败则刷新页面 $ npm run server --inline --hot
这个是在package.json里的设置,这样设置比在webpack.config.js设置更加简单。所以我们也可以这样使用哦。接着我们继续配置webpack.config.js中HotModuleReplacementPlugin,因为它是wbpack模块自带的,所以引入webpack后,就可以直接在plugins配置即可。
plugins: [ new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件实例 new HtmlWebpackPlugin({ title: 'Hello Webpack', template: path.join(__dirname, 'index.html') }), new miniCssExtractPlugin({ filename: 'index.css' }), new CleanWebpackPlugin(), // 传入要清理的文件夹名称、 new webpack.HashedModuleIdsPlugin() // 热更新插件 ]
除了这里配置外,我们还要到入口index.js里加入如下代码
//如果模块启用了HMR,就可以用 module.hot.accept(),监听模块的更新。 if (module.hot) { module.hot.accept('./helper.js', function() { header() }) }
当我们运行npm run server就可以看到控制台的输出:
插件我们就先了解到这里,更多插件使用可以查看官网。一起学习,一起进步。
查阅资料:
1)https://blog.csdn.net/cc18868876837/article/details/103238733 (CleanWebpackPlugin is not a constructor 的错误处理)
2)https://www.codercto.com/a/4836.html (webpack-dev-server 中 inline 和 HMR 的区别)
3)https://www.webpackjs.com/plugins/ (webpack官网plugins)