前言
postcss是一个非常强大的css处理器(说它是预处理或者后处理器都是不准确的, 就是一个类似babel之与js的存在),可以让我们前端开发者使用js语言,让css完成非常多很酷炫的操作, 甚至赋予css一定的编程能力。 而本篇博客只是一个抛砖引玉的作用, 后续有机会或者时间会再更加深入研究一下postcss。
由于公司项目组件库开发使用的rollup开发, 而遇到字体,图片等静态资源, rollup没有一个能配合scss/postcss的一个好用的插件。故自己研究了一下postcss,先埋个坑, 后续这篇博客可能会变成一个postcss专题。这里先介绍一下postcss插件开发
实现
Note: 该插件是基于postcss7开发的, postcss8改动还是蛮大的, 由于没有时间去升级整个工具链的postcss插件, 所以这个插件也是基于postcss7开发的。后续可能会考虑升级到postcss8
我的插件其实只需要实现一个功能, 就是copy scss文件里引用的静态资源到dist文件夹下, 这样不需要使用蹩脚的rollup copy插件,可以让开发和打包完成后的静态资源目录都是对的,将真正的处理交给使用组件库的项目。 由调用者选择如何处理静态资源, 组件库只需要保证组件库里的静态资源正确即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| const postcss = require('postcss'); const path = require('path'); const fs = require('fs');
const defaultOption = { baseDir: '.', };
module.exports = postcss.plugin('postcss-plugin-copy-url', (opts) => { const options = Object.assign(defaultOption, opts); const urlReg = /url\([\S\s]+\)/; if (!fs.existsSync(options.baseDir)) { fs.mkdirSync(options.baseDir); } return function copyUrl(root) { root.walkRules((rule) => { rule.walkDecls((decl) => { const { value } = decl; if (urlReg.exec(value)) { const file = decl.source.input.file || options.file; const matchValue = urlReg.exec(value)[0]; const assetsUrl = matchValue.replace(/\s*/g, '').substring(5, matchValue.length - 2); const basePath = path.dirname(file); const realAssetUrl = path.resolve(basePath, assetsUrl); const fileName = path.basename(assetsUrl); const targetFile = path.resolve(options.baseDir, fileName); const readStream = fs.createReadStream(realAssetUrl); const writeStream = fs.createWriteStream(targetFile); readStream.pipe(writeStream);
decl.value = `url("${fileName}")`; } }); }); }; });
|
使用
为什么postcss生态没有一个符合我要求的插件, 究其原因是因为我找到的几款插件都不能很好的和rollup scss/sass这两个插件配合。这两个插件共同特点都是不会给postcss插件传入文件, 即无法通过postcss的内部api获取到scss文件路径, 故而无法搜索到我们使用相对路径的静态资源。 我这里是结合rollup-plugin-sass 这个插件, 因为这个插件不需要我去修改源码或者很复杂的循环操作,我就能把文件路径传给postcss
1 2 3 4 5 6 7 8 9 10 11
|
const copyUrl = require('./plugins/copyUrl');
sass({ processor: (css, id) => postcss([autoprefixer(), px2rem({ remUnit: 75, remPrecision: 5 }), copyUrl({ baseDir: './dist', file: id })]) .process(css) .then((result) => result.css), output: 'dist/bundle.css', }),
|
结语
其实这个插件的开发过程, 我也对整个postcss生态做了一个大概的了解。 甚至我还买了本电子书,专门研究postcss生态及插件开发, 因为国内对这块的资料很少,埋个坑先, 后续可能会出一个升级postcss8或者一个postcss整个生态及插件开发的介绍