loader-runner 介绍

定义:loader-runner 允许在不安装 webpack 的情况下,允许 loaders
作用

  • 作为 webpack 的依赖,webpack 中使用它执行 loader
  • 进行 loader 的开发和调试

    loader 的参数获取

    通过 loader-utils 的 getOptions 方法获取
    image.png

    loader 异常处理

    loader 内直接通过 throw 抛出
    通过 this.callback 传递错误
    image.png

    loader 的异步处理

    通过 this.async 来返回一个异步函数

  • 第一个参数是 Error,第二个参数是处理结果

image.png

loader 中使用缓存

webpack 中默认开启 loader 缓存

  • 可以通过 this.cacheable(false) 关掉缓存

缓存条件:loader 的结果在相同的输入下有确定的输出

  • 有依赖的 loader 无法使用缓存

    loader 如何进行文件输出

    通过 this.emitFile进行文件输出
    image.png

开发一个 raw-loader

目录 |-loaders |-raw-loader.js |-demo.txt |-run-loader.js

  1. // raw-loader.js
  2. module.exports = function (source) {
  3. const json = JSON.stringify(source)
  4. .replace(/\u2028/g, '\\u2028')
  5. .replace(/\u2029/g, '\\u2029')
  6. // return `export default ${json}`; // 这种方式返回也行
  7. this.callback(null, json)
  8. }
  1. // run-loader.js
  2. const { runLoaders } = require('loader-runner');
  3. const fs = require('fs');
  4. const path = require('path');
  5. const config = {
  6. resource: path.join(__dirname, './loaders/demo.txt'),
  7. loaders: [
  8. path.join(__dirname, './loaders/raw-loader.js'),
  9. ],
  10. context: {
  11. minimize: true,
  12. },
  13. readResource: fs.readFile.bind(fs)
  14. }
  15. const callback = (err, result) => {
  16. err ? console.error(err) : console.log(result)
  17. }
  18. runLoaders(config, callback)

开发一个自动合成雪碧图的 loader

image.png

准备知识:如何将两张图片合成一张图片

使用 spritesmith —— https://www.npmjs.com/package/spritesmith
image.png

开始实现

目录 |-dist |-loaders |-images |-sprite-loader.js |-run-loader.js

  1. /* index.css */
  2. .img1 {
  3. background-image: url('./images/fork.png?__sprite');
  4. }
  5. .img2 {
  6. background-image: url('./images/github.png?__sprite');
  7. }
  8. .img3 {
  9. background-image: url('./images/twitter.png?__sprite');
  10. }
  1. // sprite-loader.js
  2. const Spritesmith = require('spritesmith');
  3. const fs = require('fs');
  4. const path = require('path');
  5. module.exports = function (source) {
  6. const callback = this.async();
  7. const regAll = /url\('([\S]+\?__sprite)'\)/g;
  8. const imgs = source.match(regAll);
  9. const matchImgs = [];
  10. const reg = /url\('([\S]+)\?__sprite'\)/;
  11. for (let i in imgs) {
  12. const imgPath = reg.exec(imgs[i])[1];
  13. matchImgs.push(path.join(__dirname, imgPath));
  14. }
  15. Spritesmith.run({
  16. src: matchImgs
  17. }, (err, result) => {
  18. fs.writeFileSync(path.join(process.cwd(), 'dist/sprite.png'), result.image);
  19. // 替换 css 文件中的图片路径
  20. source = source.replace(regAll, (match) => {
  21. return 'url("dist/sprite.png")';
  22. })
  23. fs.writeFileSync(path.join(process.cwd(), 'dist/index.css'), source);
  24. callback(null, result);
  25. })
  26. }
  1. const { runLoaders } = require('loader-runner');
  2. const fs = require('fs');
  3. const path = require('path');
  4. const config = {
  5. resource: path.join(__dirname, './loaders/index.css'),
  6. loaders: [
  7. path.join(__dirname, './loaders/sprite-loader.js'),
  8. ],
  9. context: {
  10. minimize: true,
  11. },
  12. readResource: fs.readFile.bind(fs)
  13. }
  14. const callback = (err, result) => {
  15. err ? console.error(err) : console.log(result)
  16. }
  17. runLoaders(config, callback)