loader.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.pitch = pitch;
  6. exports.default = _default;
  7. var _module = _interopRequireDefault(require("module"));
  8. var _path = _interopRequireDefault(require("path"));
  9. var _loaderUtils = _interopRequireDefault(require("loader-utils"));
  10. var _NodeTemplatePlugin = _interopRequireDefault(require("webpack/lib/node/NodeTemplatePlugin"));
  11. var _NodeTargetPlugin = _interopRequireDefault(require("webpack/lib/node/NodeTargetPlugin"));
  12. var _LibraryTemplatePlugin = _interopRequireDefault(require("webpack/lib/LibraryTemplatePlugin"));
  13. var _SingleEntryPlugin = _interopRequireDefault(require("webpack/lib/SingleEntryPlugin"));
  14. var _LimitChunkCountPlugin = _interopRequireDefault(require("webpack/lib/optimize/LimitChunkCountPlugin"));
  15. var _schemaUtils = _interopRequireDefault(require("schema-utils"));
  16. var _options = _interopRequireDefault(require("./options.json"));
  17. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  18. function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
  19. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  20. const MODULE_TYPE = 'css/mini-extract';
  21. const pluginName = 'mini-css-extract-plugin';
  22. function hotLoader(content, context) {
  23. const accept = context.locals ? '' : 'module.hot.accept(undefined, cssReload);';
  24. return `${content}
  25. if(module.hot) {
  26. // ${Date.now()}
  27. var cssReload = require(${_loaderUtils.default.stringifyRequest(context.context, _path.default.join(__dirname, 'hmr/hotModuleReplacement.js'))})(module.id, ${JSON.stringify(_objectSpread({}, context.options, {
  28. locals: !!context.locals
  29. }))});
  30. module.hot.dispose(cssReload);
  31. ${accept}
  32. }
  33. `;
  34. }
  35. const exec = (loaderContext, code, filename) => {
  36. const module = new _module.default(filename, loaderContext);
  37. module.paths = _module.default._nodeModulePaths(loaderContext.context); // eslint-disable-line no-underscore-dangle
  38. module.filename = filename;
  39. module._compile(code, filename); // eslint-disable-line no-underscore-dangle
  40. return module.exports;
  41. };
  42. const findModuleById = (modules, id) => {
  43. for (const module of modules) {
  44. if (module.id === id) {
  45. return module;
  46. }
  47. }
  48. return null;
  49. };
  50. function pitch(request) {
  51. const options = _loaderUtils.default.getOptions(this) || {};
  52. (0, _schemaUtils.default)(_options.default, options, 'Mini CSS Extract Plugin Loader');
  53. const loaders = this.loaders.slice(this.loaderIndex + 1);
  54. this.addDependency(this.resourcePath);
  55. const childFilename = '*'; // eslint-disable-line no-path-concat
  56. const publicPath = typeof options.publicPath === 'string' ? options.publicPath.endsWith('/') ? options.publicPath : `${options.publicPath}/` : typeof options.publicPath === 'function' ? options.publicPath(this.resourcePath, this.rootContext) : this._compilation.outputOptions.publicPath;
  57. const outputOptions = {
  58. filename: childFilename,
  59. publicPath
  60. };
  61. const childCompiler = this._compilation.createChildCompiler(`${pluginName} ${request}`, outputOptions);
  62. new _NodeTemplatePlugin.default(outputOptions).apply(childCompiler);
  63. new _LibraryTemplatePlugin.default(null, 'commonjs2').apply(childCompiler);
  64. new _NodeTargetPlugin.default().apply(childCompiler);
  65. new _SingleEntryPlugin.default(this.context, `!!${request}`, pluginName).apply(childCompiler);
  66. new _LimitChunkCountPlugin.default({
  67. maxChunks: 1
  68. }).apply(childCompiler); // We set loaderContext[MODULE_TYPE] = false to indicate we already in
  69. // a child compiler so we don't spawn another child compilers from there.
  70. childCompiler.hooks.thisCompilation.tap(`${pluginName} loader`, compilation => {
  71. compilation.hooks.normalModuleLoader.tap(`${pluginName} loader`, (loaderContext, module) => {
  72. // eslint-disable-next-line no-param-reassign
  73. loaderContext.emitFile = this.emitFile;
  74. loaderContext[MODULE_TYPE] = false; // eslint-disable-line no-param-reassign
  75. if (module.request === request) {
  76. // eslint-disable-next-line no-param-reassign
  77. module.loaders = loaders.map(loader => {
  78. return {
  79. loader: loader.path,
  80. options: loader.options,
  81. ident: loader.ident
  82. };
  83. });
  84. }
  85. });
  86. });
  87. let source;
  88. childCompiler.hooks.afterCompile.tap(pluginName, compilation => {
  89. source = compilation.assets[childFilename] && compilation.assets[childFilename].source(); // Remove all chunk assets
  90. compilation.chunks.forEach(chunk => {
  91. chunk.files.forEach(file => {
  92. delete compilation.assets[file]; // eslint-disable-line no-param-reassign
  93. });
  94. });
  95. });
  96. const callback = this.async();
  97. childCompiler.runAsChild((err, entries, compilation) => {
  98. if (err) {
  99. return callback(err);
  100. }
  101. if (compilation.errors.length > 0) {
  102. return callback(compilation.errors[0]);
  103. }
  104. compilation.fileDependencies.forEach(dep => {
  105. this.addDependency(dep);
  106. }, this);
  107. compilation.contextDependencies.forEach(dep => {
  108. this.addContextDependency(dep);
  109. }, this);
  110. if (!source) {
  111. return callback(new Error("Didn't get a result from child compiler"));
  112. }
  113. let text;
  114. let locals;
  115. try {
  116. text = exec(this, source, request);
  117. locals = text && text.locals;
  118. if (!Array.isArray(text)) {
  119. text = [[null, text]];
  120. } else {
  121. text = text.map(line => {
  122. const module = findModuleById(compilation.modules, line[0]);
  123. return {
  124. identifier: module.identifier(),
  125. content: line[1],
  126. media: line[2],
  127. sourceMap: line[3]
  128. };
  129. });
  130. }
  131. this[MODULE_TYPE](text);
  132. } catch (e) {
  133. return callback(e);
  134. }
  135. let resultSource = `// extracted by ${pluginName}`;
  136. const result = locals ? `\nmodule.exports = ${JSON.stringify(locals)};` : '';
  137. resultSource += options.hmr ? hotLoader(result, {
  138. context: this.context,
  139. options,
  140. locals
  141. }) : result;
  142. return callback(null, resultSource);
  143. });
  144. }
  145. function _default() {}