美文网首页
以css-loader 主干为例学习loader

以css-loader 主干为例学习loader

作者: jluemmmm | 来源:发表于2020-12-29 20:57 被阅读0次

使用 postcss-icss-parserpostcss-import-parserpostcss-url-parser 插件对 async loader(content, map, meta) 传入参数进行处理,在 callback 中传入处理后的结果。

"use strict";

Object.defineProperty(exports, "__esModule", { /* 用于表明是一个es模块 */
  value: true
});
exports.default = loader;

var _loaderUtils = require("loader-utils");

var _postcss = _interopRequireDefault(require("postcss"));

var _package = _interopRequireDefault(require("postcss/package.json"));

var _schemaUtils = require("schema-utils");

var _semver = require("semver");

var _CssSyntaxError = _interopRequireDefault(require("./CssSyntaxError"));

var _Warning = _interopRequireDefault(require("./Warning"));

var _options = _interopRequireDefault(require("./options.json"));

var _plugins = require("./plugins");

var _utils = require("./utils");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/* MIT License http://www.opensource.org/licenses/mit-license.php  Author Tobias Koppers @sokra*/

/* 输入 content map meta */
async function loader(content, map, meta) {
  const rawOptions = (0, _loaderUtils.getOptions)(this); 
  /* (0, obj.func)()这种调用方式将方法调用转变为函数调用, 为了让 func 中的 this 指向window, 不指向 obj*/
  (0, _schemaUtils.validate)(_options.default, rawOptions, {
    name: 'CSS Loader',
    baseDataPath: 'options'
  });
  const plugins = [];
  const callback = this.async();
  let options;

  try {
    options = (0, _utils.normalizeOptions)(rawOptions, this);
  } catch (error) {
    callback(error);
    return;
  }

  const replacements = [];
  const exports = [];

  if ((0, _utils.shouldUseModulesPlugins)(options)) { /* options.modules.compileType === 'module'; */
    plugins.push(...(0, _utils.getModulesPlugins)(options, this)); /* 更新 plugin, plugin内部的机制不再研究 */
  }

  const importPluginImports = [];
  const importPluginApi = [];

  if ((0, _utils.shouldUseImportPlugin)(options)) { /* 是否使用 import 插件 */
    const resolver = this.getResolve({
      conditionNames: ['style'],
      extensions: ['.css'],
      mainFields: ['css', 'style', 'main', '...'],
      mainFiles: ['index', '...'],
      restrictions: [/\.css$/i]
    });
    plugins.push((0, _plugins.importParser)({
      imports: importPluginImports,
      api: importPluginApi,
      context: this.context,
      rootContext: this.rootContext,
      filter: (0, _utils.getFilter)(options.import, this.resourcePath),
      resolver,
      urlHandler: url => (0, _loaderUtils.stringifyRequest)(this, (0, _utils.getPreRequester)(this)(options.importLoaders) + url)
    }));
  }

  const urlPluginImports = [];

  if ((0, _utils.shouldUseURLPlugin)(options)) { /* 是否使用 url 插件 */
    const urlResolver = this.getResolve({
      conditionNames: ['asset'],
      mainFields: ['asset'],
      mainFiles: [],
      extensions: []
    });
    plugins.push((0, _plugins.urlParser)({
      imports: urlPluginImports,
      replacements,
      context: this.context,
      rootContext: this.rootContext,
      filter: (0, _utils.getFilter)(options.url, this.resourcePath),
      resolver: urlResolver,
      urlHandler: url => (0, _loaderUtils.stringifyRequest)(this, url)
    }));
  }

  const icssPluginImports = [];
  const icssPluginApi = [];

  if ((0, _utils.shouldUseIcssPlugin)(options)) { /* 是否使用 icss 插件 */
    const icssResolver = this.getResolve({
      conditionNames: ['style'],
      extensions: [],
      mainFields: ['css', 'style', 'main', '...'],
      mainFiles: ['index', '...']
    });
    plugins.push((0, _plugins.icssParser)({
      imports: icssPluginImports,
      api: icssPluginApi,
      replacements,
      exports,
      context: this.context,
      rootContext: this.rootContext,
      resolver: icssResolver,
      urlHandler: url => (0, _loaderUtils.stringifyRequest)(this, (0, _utils.getPreRequester)(this)(options.importLoaders) + url)
    }));
  } // Reuse CSS AST (PostCSS AST e.g 'postcss-loader') to avoid reparsing


  if (meta) {
    const {
      ast
    } = meta;

    if (ast && ast.type === 'postcss' && (0, _semver.satisfies)(ast.version, `^${_package.default.version}`)) {
      // eslint-disable-next-line no-param-reassign
      content = ast.root;
    }
  }

  const {
    resourcePath
  } = this;
  let result;

  try {
    result = await (0, _postcss.default)(plugins).process(content, {
      hideNothingWarning: true,
      from: resourcePath,
      to: resourcePath,
      map: options.sourceMap ? {
        prev: map ? (0, _utils.normalizeSourceMap)(map, resourcePath) : null,
        inline: false,
        annotation: false
      } : false
    });
  } catch (error) {
    if (error.file) {
      this.addDependency(error.file);
    }

    callback(error.name === 'CssSyntaxError' ? new _CssSyntaxError.default(error) : error);
    return;
  }

  for (const warning of result.warnings()) {
    this.emitWarning(new _Warning.default(warning));
  }

  const imports = [].concat(icssPluginImports.sort(_utils.sort)).concat(importPluginImports.sort(_utils.sort)).concat(urlPluginImports.sort(_utils.sort));
  const api = [].concat(importPluginApi.sort(_utils.sort)).concat(icssPluginApi.sort(_utils.sort));

  if (options.modules.exportOnlyLocals !== true) {
    imports.unshift({
      importName: '___CSS_LOADER_API_IMPORT___',
      url: (0, _loaderUtils.stringifyRequest)(this, require.resolve('./runtime/api'))
    });

    if (options.sourceMap) {
      imports.unshift({
        importName: '___CSS_LOADER_API_SOURCEMAP_IMPORT___',
        url: (0, _loaderUtils.stringifyRequest)(this, require.resolve('./runtime/cssWithMappingToString'))
      });
    }
  }

  const importCode = (0, _utils.getImportCode)(imports, options);
  const moduleCode = (0, _utils.getModuleCode)(result, api, replacements, options, this);
  const exportCode = (0, _utils.getExportCode)(exports, replacements, options);
  callback(null, `${importCode}${moduleCode}${exportCode}`);
}

支线内容

var a = 1
var obj = {
  a: 2,
  func: function(){
    console.log(this.a)
  }
}
obj.func() //2
(0, obj.func)() //1

obj.func() 是一种方法调用,在方法面前放置一个逗号,会使得js解引用 (0, obj.func)() 变为函数调用
this 不指向 obj,指向 window

相关文章

网友评论

      本文标题:以css-loader 主干为例学习loader

      本文链接:https://www.haomeiwen.com/subject/bmsqoktx.html