webpack loader知识

2020-10-16  本文已影响0人  pipu

loader 知识相关

loader就是一个暴露特定函数的node模块,该函数将在一个资源应该被改loader转换时调用。在这个函数中可以通过上下文this来访问Loader API;

const {getOptions} = require('loader-utils');
const {promisify} = require('util');
const fs = require('fs');
const access = promisify(fs.access);
const readFile = promisify(fs.readFile);
const alertText = `
if(typeof alert ==='function'){
alert(3);
}
`
let nodeModulesPath = '';

function loader(content, map, meta) {
    const callback = this.async();
    if (!nodeModulesPath) {
        nodeModulesPath = `${this.rootContext}/node_modules`
    }
    if (this.context.startsWith(nodeModulesPath)) { // node_modules 中的文件
        callback(null, content, map, meta)
    } else {
        let trueContent = content;
        const options = getOptions(this);
        const {alert = false, comment = false} = options;
        console.log('options', options);
        console.log('this.context', this.context);
        if (alert) {
            trueContent = `${trueContent};${alertText};`;
        }
        if (comment) {
            const commentPath = this.resourcePath.replace(/\.jsx?$/, '.cm');
            console.log('commentPath', commentPath);
            readFile(commentPath,'utf-8').then(function (commentText) {
                console.log('commentText', commentText);
                trueContent = `${trueContent}/*${commentText}*/`;
                callback(null, trueContent, map, meta);
            }).catch(function () {
                console.log('not found comment file')
                callback(null, trueContent, map, meta);
            })
        } else {
            callback(null, trueContent, map, meta);
        }
    }
}

module.exports = loader;

一些准侧

一些关于创建一个loader的准则
Keep them simple.
Utilize chaining.
Emit modular output.
Make sure they're stateless.
Employ loader utilities.
Mark loader dependencies.
Resolve module dependencies.
Extract common code.
Avoid absolute paths.
Use peer dependencies.

file-loader

filte-loader 源码简单分析,查看加载资源,将资源输出到生产文件中去
调用interpolateName方法生成插入的文件名称,可以包含文件路径,插入的文件名称是在不考虑发布路径(publicPath)的情况下的引用路径。

import { getOptions, interpolateName } from 'loader-utils';
  const url = interpolateName(this, name, {
    context,
    content,
    regExp: options.regExp,
  });

根据用户设置了输出路径,来调整输出路径

  let outputPath = url;

  if (options.outputPath) {
    if (typeof options.outputPath === 'function') {
      outputPath = options.outputPath(url, this.resourcePath, context);
    } else {
      outputPath = path.posix.join(options.outputPath, url);
    }
  }

确定发布的路径

  let publicPath = `__webpack_public_path__ + ${JSON.stringify(outputPath)}`;

  if (options.publicPath) {
    if (typeof options.publicPath === 'function') {
      publicPath = options.publicPath(url, this.resourcePath, context);
    } else {
      publicPath = `${
        options.publicPath.endsWith('/')
          ? options.publicPath
          : `${options.publicPath}/`
      }${url}`;
    }

    publicPath = JSON.stringify(publicPath);
  }

  if (options.postTransformPublicPath) {
    publicPath = options.postTransformPublicPath(publicPath);
  }

输出路径将文件放置到相应的输出目录中去,发布路径将告知模块系统如何加载对应的文件资源


  if (typeof options.emitFile === 'undefined' || options.emitFile) {
   this.emitFile(outputPath, content, null, { immutable });
  }

  const esModule =
    typeof options.esModule !== 'undefined' ? options.esModule : true;

  return `${esModule ? 'export default' : 'module.exports ='} ${publicPath};`;
}

通过查看file-loader的原码可以看出,file-loader的功能就是将通过该loader处理的资源文件做复制处理并获得文件最终的路径告知webpack模块系统其正确的加载路径。同时也能看出在编写该loader中的一些符合webpack推荐的规则:

参考文章

深入浅出 Webpack

上一篇下一篇

猜你喜欢

热点阅读