原文
前言
有时候,市面上的webpack loader并不完全符合我们的需求,所以,我们不得不自己从0开始写一个,或者是在别人写的loader基础之上进行修改。
无论哪种,都需要我们对webpack加载loader的方式有所了解。实现
出招吧~
在github上创建项目
创建本地项目
1、git clone项目到本地
2、初始化npmnpm init
填写完npm init的一路提示下来以后,我们看下文件结构:
.├── README.md└── package.json
3、安装webpack
npm i -D webpack
4、设置一下package.json里的scripts命令:
"scripts": { "dev": "webpack"},
这样的话,基本的工具就准备完毕了。
编写webpack.config.js
1、创建webpack.config.js
.├── README.md├── node_modules├── package-lock.json├── package.json└── webpack.config.js
2、编辑webpack.config.js
const path = require('path')module.exports = { entry: { app: path.resolve('demo/index.js') }, output: { path: path.resolve('dist'), filename: 'index.js' }, module: { rules: [ { test: /\.js$/, loader: path.resolve('src/loader-test.js'), options: { speak: 'wang~', } } ] }}
因为我们是从0开始编写的,所以不得不先从简单到复杂。
所以,如上,我们通过path引用的方式来使用loader。并且,我们配置了option,作为参数。index则是需要处理的文件。编写index.js
const cat = 'kitty'console.log(cat)
编写loader-test.js
// loader-utils作为工具类引入(作为webpack依赖,所以在安装webpack时候就带上了)const loaderUtils = require('loader-utils')// loader调用的时候,会将源数据和sourcemap作为参数传入函数module.exports = function(source, inputSourceMap) { const code = source const map = inputSourceMap // loaderUtils.getOptions 可以获取到设置loader时候设置的options // 当然loaderUtils还有很多其他有用的方法,详情可以看 https://github.com/webpack/loader-utils const loaderOptions = loaderUtils.getOptions(this) || {}; console.log(source) console.log(loaderOptions) // loader需要将自己的值传给下一个loader,并且,loader不免会有异步操作 // 因此需要回调来证明自己已经处理结束了 this.callback(null, code, map)}
先看下目录结构,为了不影响视觉,我忽略了node_module文件:
.├── README.md├── demo│ └── index.js├── package-lock.json├── package.json├── src│ └── loader-test.js└── webpack.config.js
好,让我们运行一下webpack,看一下效果:
npm run dev
...const cat = 'kitty'console.log(cat){ speak: 'wang~' }...
正如我们写的loader,打印出了index.js的源码,以及,webpack.config.js配置loader时候的options。
是不是有点儿小兴奋?写点有意义的功能
虽然说是教程,但是这样的小例子的确有点太过简单了,我们可以做点有意义点的功能。
比如,我们想把js中px全部替换成vw,比例就按照1vw = 10px
吧。(我相信很多朋友会觉得为啥替换js,而不是css或者scss。因为,会涉及更多的webapck配置,比较无聊和对本章内容没什么作用,所以,我觉得还是越简单越好,就拿js举例子吧)好,计划有了,开始行动吧! 重新编辑index.js
const parentStyle = ` background: #fdc; width: 1200px; height: 600px; box-sizing: border-box; padding: 150px 300px;`const childStyle = ` background: #cdf; width: 600px; height: 300px;`const parent = document.getElementById('parent')const child = document.getElementById('child')parent.style.cssText = parentStylechild.style.cssText = childStyle
为了更好展示,我们再写个html吧
Document
让启动demo更顺畅
一不做二不休,为了更顺畅的看效果,我们加个webpack-dev-server自动启动吧。同时,顺带着,将html-webpack-plugin和clean-webpack-plugin也都加上。
关于写demo,我觉得,是写npm modules必须要有的东西,如果没有demo,没有顺畅的启动demo操作。别说别人懒得看,自己都懒得启动了。好,我们再看下现在的webpack配置:const path = require('path')const HtmlWebpackPlugin = require('html-webpack-plugin')const CleanWebpackPlugin = require('clean-webpack-plugin')module.exports = { entry: { app: path.resolve('demo/index.js') }, output: { path: path.resolve('dist'), filename: 'index.js' }, module: { rules: [ { test: /\.js$/, loader: path.resolve('src/loader-test.js') } ] }, plugins: [ // 清理dist new CleanWebpackPlugin('dist'), // 将js打入html new HtmlWebpackPlugin({ filename: 'index.html', template: path.resolve('demo/index.html'), chunks: ['app'] // 因为只有一个页面,这行不写也可以 }) ]}
修改下package.json里的scripts命令:
"scripts": { "dev": "webpack-dev-server --open"},
然后,启动实验一下,npm run dev
。
没问题,进入下一步~
正式修改loader
让我们重新编辑loader-test.js吧:
... // 替换px const regex = /(\d+?)px/g code = code.replace(regex, function(match, p1) { return p1/10 + 'vw' }) ...}
然后,再重新启动一下,我们会发现,px都被替换成了vw了,而且比例为1vw = 10px,成功!
当然,有同学肯定会想到,要是这个比例可以自己设置那就更好了。实现方式当然也很简单啊,还记得我们之前是怎么获取loader中options配置的speak吗?我相信同学完全可以独立完成了。怎么把包做成npm module,然后发到npm 上,以后都能用呢?
这个的话,其实是我之前已经写过这样的文章了,同学们可以转到
本文项目地址
最后,希望喜欢的同学能给star哦
说点题外话,不知道为什么webpack官网对loader的介绍那么简短,很难单单根据文档就写出loader来。所以还建议看些别人写的loader,如babel-loader等。