forked from peerigon/extract-loader
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
444 additions
and
162 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
"use strict";Object.defineProperty(exports, "__esModule", { value: true });var _assign = require("babel-runtime/core-js/object/assign");var _assign2 = _interopRequireDefault(_assign);var _promise = require("babel-runtime/core-js/promise");var _promise2 = _interopRequireDefault(_promise);var _map = require("babel-runtime/core-js/map");var _map2 = _interopRequireDefault(_map);var _asyncToGenerator2 = require("babel-runtime/helpers/asyncToGenerator");var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); | ||
|
||
|
||
|
||
|
||
|
||
|
||
/** | ||
* @typedef {Object} LoaderContext | ||
* @property {function} cacheable | ||
* @property {function} async | ||
* @property {function} addDependency | ||
* @property {function} loadModule | ||
* @property {string} resourcePath | ||
* @property {object} options | ||
*/ | ||
|
||
/** | ||
* Executes the given module's src in a fake context in order to get the resulting string. | ||
* | ||
* @this LoaderContext | ||
* @param {string} src | ||
* @throws Error | ||
*/let extractLoader = (() => {var _ref = (0, _asyncToGenerator3.default)( | ||
function* (src) { | ||
const done = this.async(); | ||
const options = (0, _loaderUtils.getOptions)(this) || {}; | ||
const publicPath = getPublicPath(options, this); | ||
|
||
this.cacheable(); | ||
|
||
try { | ||
done(null, (yield evalDependencyGraph({ | ||
loaderContext: this, | ||
src, | ||
filename: this.resourcePath, | ||
publicPath }))); | ||
|
||
} catch (error) { | ||
done(error); | ||
} | ||
});return function extractLoader(_x) {return _ref.apply(this, arguments);};})();var _vm = require("vm");var _vm2 = _interopRequireDefault(_vm);var _path = require("path");var _path2 = _interopRequireDefault(_path);var _loaderUtils = require("loader-utils");var _resolve = require("resolve");var _resolve2 = _interopRequireDefault(_resolve);var _btoa = require("btoa");var _btoa2 = _interopRequireDefault(_btoa);var _babelCore = require("babel-core");var babel = _interopRequireWildcard(_babelCore);function _interopRequireWildcard(obj) {if (obj && obj.__esModule) {return obj;} else {var newObj = {};if (obj != null) {for (var key in obj) {if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];}}newObj.default = obj;return newObj;}}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} | ||
|
||
function evalDependencyGraph({ loaderContext, src, filename, publicPath = "" }) {let evalModule = (() => {var _ref2 = (0, _asyncToGenerator3.default)( | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
function* (src, filename) { | ||
const rndPlaceholder = "__EXTRACT_LOADER_PLACEHOLDER__" + rndNumber() + rndNumber(); | ||
|
||
src = babel.transform(src, { | ||
babelrc: false, | ||
presets: [ | ||
[ | ||
require("babel-preset-env"), { | ||
modules: "commonjs", | ||
targets: { nodejs: "current" } }]], | ||
|
||
|
||
|
||
plugins: [require("babel-plugin-add-module-exports")] }). | ||
code; | ||
|
||
const script = new _vm2.default.Script(src, { | ||
filename, | ||
displayErrors: true }); | ||
|
||
const newDependencies = []; | ||
const exports = {}; | ||
const sandbox = (0, _assign2.default)({}, global, { | ||
module: { | ||
exports }, | ||
|
||
exports, | ||
__webpack_public_path__: publicPath, // eslint-disable-line camelcase | ||
require: function (_require) {function require(_x4) {return _require.apply(this, arguments);}require.toString = function () {return _require.toString();};return require;}(function (givenRelativePath) {var _extractQueryFromPath = | ||
extractQueryFromPath(givenRelativePath);const relativePathWithoutQuery = _extractQueryFromPath.relativePathWithoutQuery,query = _extractQueryFromPath.query; | ||
const indexOfLastExclMark = relativePathWithoutQuery.lastIndexOf("!"); | ||
const loaders = givenRelativePath.slice(0, indexOfLastExclMark + 1); | ||
const relativePath = relativePathWithoutQuery.slice(indexOfLastExclMark + 1); | ||
const absolutePath = _resolve2.default.sync(relativePath, { | ||
basedir: _path2.default.dirname(filename) }); | ||
|
||
const ext = _path2.default.extname(absolutePath); | ||
|
||
if (moduleCache.has(absolutePath)) { | ||
return moduleCache.get(absolutePath); | ||
} | ||
|
||
// If the required file is a js file, we just require it with node's require. | ||
// If the required file should be processed by a loader we do not touch it (even if it is a .js file). | ||
if (loaders === "" && ext === ".js") { | ||
// Mark the file as dependency so webpack's watcher is working for the css-loader helper. | ||
// Other dependencies are automatically added by loadModule() below | ||
loaderContext.addDependency(absolutePath); | ||
|
||
const exports = require(absolutePath); // eslint-disable-line import/no-dynamic-require | ||
|
||
moduleCache.set(absolutePath, exports); | ||
|
||
return exports; | ||
} | ||
|
||
newDependencies.push({ | ||
absolutePath, | ||
absoluteRequest: loaders + absolutePath + query }); | ||
|
||
|
||
return rndPlaceholder + "_" + (newDependencies.length - 1) + "_"; | ||
}) }); | ||
|
||
|
||
script.runInNewContext(sandbox); | ||
|
||
const extractedDependencyContent = yield _promise2.default.all( | ||
newDependencies.map((() => {var _ref3 = (0, _asyncToGenerator3.default)(function* ({ absolutePath, absoluteRequest }) { | ||
const src = yield loadModule(absoluteRequest); | ||
|
||
return evalModule(src, absolutePath); | ||
});return function (_x5) {return _ref3.apply(this, arguments);};})())); | ||
|
||
const contentWithPlaceholders = extractExports(sandbox.module.exports); | ||
let extractedContent = contentWithPlaceholders; | ||
|
||
for (let i = 0; i < extractedDependencyContent.length; i++) { | ||
extractedContent = extractedContent.replace( | ||
new RegExp(rndPlaceholder + "_" + i + "_", "g"), | ||
extractedDependencyContent[i]); | ||
|
||
} | ||
|
||
moduleCache.set(filename, extractedContent); | ||
|
||
return extractedContent; | ||
});return function evalModule(_x2, _x3) {return _ref2.apply(this, arguments);};})();const moduleCache = new _map2.default();function loadModule(filename) {return new _promise2.default((resolve, reject) => {// loaderContext.loadModule automatically calls loaderContext.addDependency for all requested modules | ||
loaderContext.loadModule(filename, (error, src) => {if (error) {reject(error);} else {resolve(src);}});});}function extractExports(exports) {const hasBtoa = "btoa" in global;const previousBtoa = global.btoa;global.btoa = _btoa2.default;try {return exports.toString();} catch (error) {throw error;} finally {if (hasBtoa) {global.btoa = previousBtoa;} else {delete global.btoa;}}}function extractQueryFromPath(givenRelativePath) {const indexOfLastExclMark = givenRelativePath.lastIndexOf("!");const indexOfQuery = givenRelativePath.lastIndexOf("?");if (indexOfQuery !== -1 && indexOfQuery > indexOfLastExclMark) {return { relativePathWithoutQuery: givenRelativePath.slice(0, indexOfQuery), query: givenRelativePath.slice(indexOfQuery) };}return { relativePathWithoutQuery: givenRelativePath, query: "" };} | ||
return evalModule(src, filename); | ||
} | ||
|
||
/** | ||
* @returns {string} | ||
*/ | ||
function rndNumber() { | ||
return Math.random(). | ||
toString(). | ||
slice(2); | ||
} | ||
|
||
// getPublicPath() encapsulates the complexity of reading the publicPath from the current | ||
// webpack config. Let's keep the complexity in this function. | ||
/* eslint-disable complexity */ | ||
/** | ||
* Retrieves the public path from the loader options, context.options (webpack <4) or context._compilation (webpack 4+). | ||
* context._compilation is likely to get removed in a future release, so this whole function should be removed then. | ||
* See: https://github.com/peerigon/extract-loader/issues/35 | ||
* | ||
* @deprecated | ||
* @param {Object} options - Extract-loader options | ||
* @param {Object} context - Webpack loader context | ||
* @returns {string} | ||
*/ | ||
function getPublicPath(options, context) { | ||
if ("publicPath" in options) { | ||
return typeof options.publicPath === "function" ? options.publicPath(context) : options.publicPath; | ||
} | ||
|
||
if (context.options && context.options.output && "publicPath" in context.options.output) { | ||
return context.options.output.publicPath; | ||
} | ||
|
||
if (context._compilation && context._compilation.outputOptions && "publicPath" in context._compilation.outputOptions) { | ||
return context._compilation.outputOptions.publicPath; | ||
} | ||
|
||
return ""; | ||
} | ||
/* eslint-enable complexity */ | ||
|
||
// For CommonJS interoperability | ||
module.exports = extractLoader;exports.default = | ||
extractLoader; |
Oops, something went wrong.