❝最近看一下webpack相关的内容,谈一下如何编写loader和plugincss
❞
相信你们对webpack也有必定的了解,其实深刻浅出webpack这本书也看了不少遍,每一次看都会有一些细节以前没有注意到,我以为其实能够把它当成是一本工具书来看,以前我也是只看配置都有点让你看不过来,更别说其余的了。html
因此今天我就说一下如何编写一个loader与plugin,以及它们之间有什么却别等。vue
Loader其实就是一个转换器,把你输入的内容翻译一遍,本质上是没有什么变化的,就像中文翻译成英文同样。咱们其实在不知不觉当中也使用了不少的Loader,可是咱们没有过多关注而已。经常使用的Loader有如下几类:node
「语言转换类」webpack
babel-loader
:把ES6转成ES5
ts-loader
:把TypeScript转成JavaScript
sass-loader
:把scss/sass转成css
less-loader
:把less代码转成css
css-loader
:加载css,文件导入等
「文件加载类」git
raw-loader
:把文本文件加载到代码中
file-loader
:将文件输出到一个文件夹中,使用相对路径引用输出文件
source-map-loader
:加载额外的SourceMap文件,方便断点调试
node-loader
:加载Node.js原生模块的.node文件
json-loader
:加载json文件
「其余loader」github
vue-loader
:加载.vue文件
ui-component-loader
:按需加载组件库
i18n-loader
:加载多语言版本
ignore-loader
:忽略部分文件
module.exports = {
module:{
rules:[
{
test:/\.scss/,
use:[
'style-loader',
{
'css-loader',
options:{
minimize:true
}
},
'sass-loader'
],
}
]
}
}
复制代码
以上的代码意思就是对.scss文件的转换过程,test的配置就是对某一类文件进行转换,use是使用的loader(转换器),它是一个数组,遵循从右往左的使用。先sass-loader再css-loader再style-loader。web
咱们默认的loader都是从npm上面下载的,可是假如咱们要使用本身本地写的loader怎么办呢?咱们在webpack里面有这样一个配置resolveLoader
,它的意思就是说咱们使用哪里的loader来加载文件,能够配置多个地方:面试
module.exports = {
resolveLoader:{
modules:['node_modules','yourPath']
}
}
复制代码
意思就是说咱们能够自定义loader的路径,默认就是从node_modules里面找,可是假如你的自定义loader放在本地,能够把你的路径写在yourPath里面(相对路径)。匹配规则就是从左向右查找。npm
说了这么多,咱们本身来写一个简单的loader吧,虽然是一个没有意义的loader,可是也让你们有一个简单的印象,原来写一个loader是很简单的。
npm init -y
,
npm i -D webpack webpack-cli
src/index.js
loaders/myloader.js
webpack.config.js
package.json
{
"name": "myLoader",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11"
}
}
复制代码
index.js
console.log('世界上最好的语言是PHP!')
复制代码
myLoader.js
const loaderUtils = require('loader-utils');
module.exports = function (source) {
const options = loaderUtils.getOptions(this);
const result = source.replace('PHP', options.name);
return result;
}
复制代码
webpack.config.js
const path = require("path");
module.exports = {
mode: "development",
entry: {
main: "./src/index.js",
},
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist"),
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: path.resolve(__dirname, "./loaders/myLoader.js"),
options: {
name: "JavaScript",//这里就是你要替换的值
},
},
},
],
},
};
复制代码
好了,到此为止咱们已经成功地写了一个loader,接下来咱们就测试一下是否真的work!运行npm run build
以后会输出一个dist文件夹,里面有一个main.js文件,盘它。
相对于Loader来讲,其实plugin的机制更加灵活,它能够在webpack的运行过程当中改变输出结果。简单来讲就是为输出添砖加瓦。
extract-text-webpack-plugin
:把JS中的css代码提到单独文件中
webpack-parallel-uglify-plugin
:多进程代码压缩
html-webpack-plugin
:简化HTML文件建立
dll-plugin
:提升webpack构建速度
ignore-plugin
:忽略部分文件
咱们先来看一下简单的插件是怎么编写出来的:
class myPlugin {
constructor(options){
}
apply(complier){
complier.plugin('compilation',function(compilation){
})
}
}
//导出
module.exports = myPlugin;
复制代码
「工做流程」:
俗话说,talk is cheap,show me the code
仍是沿用上面的代码结构,在根目录下面建一个myPlugins文件夹,里面建一个myPlugin.js文件,咱们就自定义一个plugin:
class myPlugin {
constructor(doneCallback, failCallback) {
this.doneCallback = doneCallback;
this.failCallback = failCallback;
}
apply(compiler) {
compiler.hooks.done.tap('myPlugin', (stats) => {
this.doneCallback(stats);
});
compiler.hooks.failed.tap('myPlugin', (err) => {
this.failCallback(err);
});
}
}
module.exports = myPlugin;
复制代码
而后咱们在webpack.config.js
文件里面先引入插件
,而后配置插件
便可。
仍是先打包一下,你会发如今打包过程当中,webpack会广播默认的事件,这里我就监听了webpack的done事件
(webpack构建成功,即将退出)和fail事件
(webpack构建失败,即将退出)。
const myPlugin = require("./plugins/myPlugin");
module.exports = {
plugins: [
new myPlugin(
() => {
//throw new Error('Error!')
console.log("成功监听到结束事件,能够执行你想要的函数!");
},
(error) => {
console.log(error);
}
),
],
}
复制代码
咱们运行以后发现是能够监听的,这里我把两种状况都试一下。首先正常构建,而后手动抛出错误,结果以下:
今天没事就折腾一下看似简单的东西,好比想看一下一些经典loader和plugin的源代码,自信的我还想看一下webpack的源代码,发现看不懂,就此打住了。
不过其实plugin和loader的区别也是面试常问的,也会问你知道怎么写loader和plugin的问题,虽然本身实现的很简单甚至有点幼稚,本身感受还好。
相信你们读了以后应该有本身的理解,之后遇到这个问题也会有本身的想法,你们实践一下就知道其中的奥秘了。
参考文章:深刻浅出Webpack
文章代码:https://github.com/wqs2019/myLoader