loader.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. var fs = require("fs");
  6. var loaderUtils = require("loader-utils");
  7. var NodeTemplatePlugin = require("webpack/lib/node/NodeTemplatePlugin");
  8. var NodeTargetPlugin = require("webpack/lib/node/NodeTargetPlugin");
  9. var LibraryTemplatePlugin = require("webpack/lib/LibraryTemplatePlugin");
  10. var SingleEntryPlugin = require("webpack/lib/SingleEntryPlugin");
  11. var LimitChunkCountPlugin = require("webpack/lib/optimize/LimitChunkCountPlugin");
  12. var NS = fs.realpathSync(__dirname);
  13. module.exports = function(source) {
  14. if(this.cacheable) this.cacheable();
  15. return source;
  16. };
  17. module.exports.pitch = function(request) {
  18. if(this.cacheable) this.cacheable();
  19. var query = loaderUtils.getOptions(this) || {};
  20. var loaders = this.loaders.slice(this.loaderIndex + 1);
  21. this.addDependency(this.resourcePath);
  22. // We already in child compiler, return empty bundle
  23. if(this[NS] === undefined) {
  24. throw new Error(
  25. '"extract-text-webpack-plugin" loader is used without the corresponding plugin, ' +
  26. 'refer to https://github.com/webpack/extract-text-webpack-plugin for the usage example'
  27. );
  28. } else if(this[NS] === false) {
  29. return "";
  30. } else if(this[NS](null, query)) {
  31. if(query.omit) {
  32. this.loaderIndex += +query.omit + 1;
  33. request = request.split("!").slice(+query.omit).join("!");
  34. loaders = loaders.slice(+query.omit);
  35. }
  36. var resultSource;
  37. if(query.remove) {
  38. resultSource = "// removed by extract-text-webpack-plugin";
  39. } else {
  40. resultSource = undefined;
  41. }
  42. var childFilename = "extract-text-webpack-plugin-output-filename"; // eslint-disable-line no-path-concat
  43. var publicPath = typeof query.publicPath === "string" ? query.publicPath : this._compilation.outputOptions.publicPath;
  44. var outputOptions = {
  45. filename: childFilename,
  46. publicPath: publicPath
  47. };
  48. var childCompiler = this._compilation.createChildCompiler("extract-text-webpack-plugin", outputOptions);
  49. childCompiler.apply(new NodeTemplatePlugin(outputOptions));
  50. childCompiler.apply(new LibraryTemplatePlugin(null, "commonjs2"));
  51. childCompiler.apply(new NodeTargetPlugin());
  52. childCompiler.apply(new SingleEntryPlugin(this.context, "!!" + request));
  53. childCompiler.apply(new LimitChunkCountPlugin({ maxChunks: 1 }));
  54. var subCache = "subcache " + NS + " " + request; // eslint-disable-line no-path-concat
  55. childCompiler.plugin("compilation", function(compilation) {
  56. if(compilation.cache) {
  57. if(!compilation.cache[subCache])
  58. compilation.cache[subCache] = {};
  59. compilation.cache = compilation.cache[subCache];
  60. }
  61. });
  62. // We set loaderContext[NS] = false to indicate we already in
  63. // a child compiler so we don't spawn another child compilers from there.
  64. childCompiler.plugin("this-compilation", function(compilation) {
  65. compilation.plugin("normal-module-loader", function(loaderContext, module) {
  66. loaderContext[NS] = false;
  67. if (module.request === request) {
  68. module.loaders = loaders.map(function(loader) {
  69. return {
  70. loader: loader.path,
  71. options: loader.options
  72. };
  73. });
  74. }
  75. });
  76. });
  77. var source;
  78. childCompiler.plugin("after-compile", function(compilation, callback) {
  79. source = compilation.assets[childFilename] && compilation.assets[childFilename].source();
  80. // Remove all chunk assets
  81. compilation.chunks.forEach(function(chunk) {
  82. chunk.files.forEach(function(file) {
  83. delete compilation.assets[file];
  84. });
  85. });
  86. callback();
  87. });
  88. var callback = this.async();
  89. childCompiler.runAsChild(function(err, entries, compilation) {
  90. if(err) return callback(err);
  91. if(compilation.errors.length > 0) {
  92. return callback(compilation.errors[0]);
  93. }
  94. compilation.fileDependencies.forEach(function(dep) {
  95. this.addDependency(dep);
  96. }, this);
  97. compilation.contextDependencies.forEach(function(dep) {
  98. this.addContextDependency(dep);
  99. }, this);
  100. if(!source) {
  101. return callback(new Error("Didn't get a result from child compiler"));
  102. }
  103. try {
  104. var text = this.exec(source, request);
  105. if(typeof text === "string")
  106. text = [[0, text]];
  107. text.forEach(function(item) {
  108. var id = item[0];
  109. compilation.modules.forEach(function(module) {
  110. if(module.id === id)
  111. item[0] = module.identifier();
  112. });
  113. });
  114. this[NS](text, query);
  115. if(text.locals && typeof resultSource !== "undefined") {
  116. resultSource += "\nmodule.exports = " + JSON.stringify(text.locals) + ";";
  117. }
  118. } catch(e) {
  119. return callback(e);
  120. }
  121. if(resultSource)
  122. callback(null, resultSource);
  123. else
  124. callback();
  125. }.bind(this));
  126. }
  127. };