mirror of
https://github.com/expo/asset-module-webpack-plugin.git
synced 2026-11-13 20:11:26 -10:00
235 lines
6.9 KiB
JavaScript
235 lines
6.9 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, '__esModule', {
|
|
value: true
|
|
});
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
|
|
|
var _mkdirp = require('mkdirp');
|
|
|
|
var _mkdirp2 = _interopRequireDefault(_mkdirp);
|
|
|
|
var _path = require('path');
|
|
|
|
var _path2 = _interopRequireDefault(_path);
|
|
|
|
var DEFAULT_FILE_SYSTEM_SYMBOL = Symbol('DefaultFileSystem');
|
|
|
|
class AssetModulePlugin {
|
|
|
|
constructor(options) {
|
|
this.options = options;
|
|
}
|
|
|
|
apply(compiler) {
|
|
var _this = this;
|
|
|
|
compiler.plugin('compilation', function (compilation, parameters) {
|
|
var addedResources = new Set();
|
|
compilation._modulesToEmit = [];
|
|
compilation.plugin('succeed-module', function (module) {
|
|
var resource = module.resource;
|
|
|
|
if (addedResources.has(resource) || !_this._shouldEmit(module)) {
|
|
return;
|
|
}
|
|
addedResources.add(resource);
|
|
compilation._modulesToEmit.push(module);
|
|
});
|
|
});
|
|
|
|
compiler.plugin('after-emit', function (compilation, callback) {
|
|
Promise.all(compilation._modulesToEmit.map(function (module) {
|
|
return _this._emitAssetModule(compiler, compilation, module);
|
|
})).then(function (result) {
|
|
callback(null, result);
|
|
}, function (error) {
|
|
console.warn(error.stack);
|
|
callback(error);
|
|
});
|
|
});
|
|
}
|
|
|
|
_emitAssetModule(compiler, compilation, module) {
|
|
var _this2 = this;
|
|
|
|
var _options = this.options;
|
|
var sourceBase = _options.sourceBase;
|
|
var destinationBase = _options.destinationBase;
|
|
var resource = module.resource;
|
|
|
|
var relativePath = _path2.default.relative(sourceBase, resource);
|
|
var destinationPath = _path2.default.resolve(destinationBase, relativePath);
|
|
if (resource === destinationPath) {
|
|
var message = `Destination path for ${ resource } matches the source path; skipping instead of overwriting the file`;
|
|
compilation.warnings.push(new Error(message));
|
|
return Promise.resolve(null);
|
|
}
|
|
|
|
var source = this._getAssetModuleSource(compilation, module);
|
|
|
|
if (!this.options.fileSystems) {
|
|
var fileSystem = compiler.outputFileSystem;
|
|
return this._writeFile(destinationPath, source, fileSystem);
|
|
}
|
|
|
|
var fileSystems = this.options.fileSystems.map(function (fileSystem) {
|
|
if (fileSystem === DEFAULT_FILE_SYSTEM_SYMBOL) {
|
|
return compiler.outputFileSystem;
|
|
}
|
|
return fileSystem;
|
|
});
|
|
|
|
var promises = fileSystems.map(function (fileSystem) {
|
|
return _this2._writeFile(destinationPath, source, fileSystem).catch(function (error) {
|
|
compilation.errors.push(error);
|
|
throw error;
|
|
});
|
|
});
|
|
return Promise.all(promises);
|
|
}
|
|
|
|
_getAssetModuleSource(compilation, module) {
|
|
var sourceBase = this.options.sourceBase;
|
|
var resource = module.resource;
|
|
var assets = module.assets;
|
|
|
|
var publicPath = compilation.mainTemplate.getPublicPath({
|
|
hash: compilation.hash
|
|
});
|
|
|
|
var assetFilename;
|
|
var assetFilenames = Object.keys(assets);
|
|
if (assetFilenames.length === 0) {
|
|
assetFilename = _path2.default.relative(sourceBase, resource);
|
|
} else {
|
|
if (assetFilenames.length > 1) {
|
|
var message = `Module at ${ resource } generated more than one asset; using the first one`;
|
|
compilation.warnings.push(new Error(message));
|
|
}
|
|
assetFilename = assetFilenames[0];
|
|
}
|
|
|
|
var fullAssetPath = publicPath + assetFilename;
|
|
return `module.exports = ${ JSON.stringify(fullAssetPath) };\n`;
|
|
}
|
|
|
|
_writeFile(filename, content, fileSystem) {
|
|
var makeDirectories = this._getMakeDirectoriesFunction(fileSystem);
|
|
return new Promise(function (resolve, reject) {
|
|
makeDirectories(_path2.default.dirname(filename), function (error) {
|
|
if (error) {
|
|
reject(error);
|
|
return;
|
|
}
|
|
|
|
fileSystem.writeFile(filename, content, function (error) {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve(null);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
_getMakeDirectoriesFunction(fileSystem) {
|
|
if (fileSystem.mkdirp) {
|
|
return fileSystem.mkdirp.bind(fileSystem);
|
|
}
|
|
return function (path, callback) {
|
|
return (0, _mkdirp2.default)(path, { fs: fileSystem }, callback);
|
|
};
|
|
}
|
|
|
|
_shouldEmit(module) {
|
|
var _options2 = this.options;
|
|
var test = _options2.test;
|
|
var include = _options2.include;
|
|
var exclude = _options2.exclude;
|
|
var resource = module.resource;
|
|
|
|
if (test && !this._matches(test, resource)) {
|
|
return false;
|
|
}
|
|
if (include && !this._matches(include, resource)) {
|
|
return false;
|
|
}
|
|
if (exclude && this._matches(exclude, resource)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
_matches(pattern, string) {
|
|
if (pattern instanceof RegExp) {
|
|
return pattern.test(string);
|
|
}
|
|
|
|
if (typeof pattern === 'string') {
|
|
var escapedPattern = '^' + pattern.replace(/[-[\]{}()*+?.\\^$|]/g, '\\$&');
|
|
var regex = new RegExp(escapedPattern);
|
|
return regex.test(string);
|
|
}
|
|
|
|
if (typeof pattern === 'function') {
|
|
return pattern(string);
|
|
}
|
|
|
|
throw new Error(`Unsupported pattern: ${ pattern }`);
|
|
}
|
|
}
|
|
|
|
AssetModulePlugin.DefaultFileSystem = DEFAULT_FILE_SYSTEM_SYMBOL;
|
|
|
|
exports.default = AssetModulePlugin;
|
|
module.exports = exports.default;
|
|
|
|
/**
|
|
* The base directory of the source assets. This is the portion of the asset
|
|
* path that will be replaced with the destination base directory.
|
|
*
|
|
* For example, if `sourceBase` is `'src/web'` and `destinationBase` is
|
|
* `'build/web'`, then an asset at `src/web/assets/icon.png` would produce a
|
|
* module at `build/web/assets/icon.png`.
|
|
*
|
|
* The source assets don't need to reside in the source base directory. This
|
|
* plugin computes the relative path from the source base directory to each
|
|
* asset and applies the same relative path to the destination base directory.
|
|
* For example, with the previous example's configuration, an asset at
|
|
* `src/favicons/favicon.png` would result in a module at
|
|
* `build/favicons/favicon.png`.
|
|
*/
|
|
|
|
/**
|
|
* The base directory of the emitted modules. See the documentation for
|
|
* `sourceBase`.
|
|
*/
|
|
|
|
/**
|
|
* A test applied to each asset's resource path to determine if this plugin
|
|
* should emit a module for the asset. The test can be any of the types that
|
|
* webpack's loader patterns support.
|
|
*/
|
|
|
|
/**
|
|
* A test applied to each asset's resource path to determine if this plugin
|
|
* should emit a module for the asset.
|
|
*/
|
|
|
|
/**
|
|
* A test applied to each asset's resource path to determine if this plugin
|
|
* should not emit a module for the asset.
|
|
*/
|
|
|
|
/**
|
|
* Overrides the file systems used to write the emitted modules. By default,
|
|
* the plugin writes to the compiler's `outputFileSystem`, but you may want
|
|
* to write the modules to another file system as well.
|
|
*
|
|
* Specify `AssetModulePlugin.DefaultFileSystem` in the array to write to the
|
|
* compiler's `outputFileSystem`.
|
|
*/ |