UNPKG

twreporter-react

Version:

React-Redux site for The Reporter Foundation in Taiwan

472 lines (363 loc) 15.8 kB
'use strict'; exports.__esModule = true; exports['default'] = write_assets; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _fsExtra = require('fs-extra'); var _fsExtra2 = _interopRequireDefault(_fsExtra); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _requireHacker = require('require-hacker'); var _requireHacker2 = _interopRequireDefault(_requireHacker); var _toolsSerializeJavascript = require('../tools/serialize-javascript'); var _toolsSerializeJavascript2 = _interopRequireDefault(_toolsSerializeJavascript); var _helpers = require('../helpers'); var _common = require('../common'); // writes webpack-assets.json file, which contains assets' file paths function write_assets(json, options, log) { // take the passed in options options = _helpers.clone(options); log.debug('running write assets webpack plugin v' + require('../../package.json').version + ' with options', options); // make webpack stats accessible for asset functions (parser, path, filter) options.webpack_stats = json; var development = options.development; if (development) { log.debug(' (development mode is on)'); } // write webpack stats json for debugging purpose if (options.debug) { // write webpack stats file log.debug('writing webpack stats to ' + options.webpack_stats_path); // write the file // (format the JSON for better readability) _fsExtra2['default'].outputFileSync(options.webpack_stats_path, JSON.stringify(json, null, 2)); } // the output object with assets var output = options.output; // populate the output object with assets populate_assets(output, json, options, log); // write webpack assets info file log.debug('writing webpack assets info to ' + options.webpack_assets_path); // format the JSON for better readability if in debug mode var assets_info = development ? JSON.stringify(output, null, 2) : JSON.stringify(output); // write the file _fsExtra2['default'].outputFileSync(options.webpack_assets_path, assets_info); } // populates the output object with assets function populate_assets(output, json, options, log) { // for each chunk name ("main", "common", ...) Object.keys(json.assetsByChunkName).forEach(function (name) { log.debug('getting javascript and styles for chunk "' + name + '"'); // get javascript chunk real file path var javascript = get_assets(name, 'js')[0]; // the second asset is usually a source map if (javascript) { log.debug(' (got javascript)'); output.javascript[name] = javascript; } // get style chunk real file path var style = get_assets(name, 'css')[0]; // the second asset is usually a source map if (style) { log.debug(' (got style)'); output.styles[name] = style; } }); // gets asset paths by name and extension of their chunk function get_assets(name) { var extension = arguments.length <= 1 || arguments[1] === undefined ? 'js' : arguments[1]; var chunk = json.assetsByChunkName[name]; // a chunk could be a string or an array, so make sure it is an array if (!Array.isArray(chunk)) { chunk = [chunk]; } return chunk // filter by extension .filter(function (name) { return _path2['default'].extname(name) === '.' + extension; }) // adjust the real path (can be http, filesystem) .map(function (name) { return options.assets_base_url + name; }); } // one can supply a custom filter var default_filter = function default_filter(module, regular_expression) { return regular_expression.test(module.name); }; // one can supply a custom namer var default_asset_path = function default_asset_path(module) { return module.name; }; // one can supply a custom parser var default_parser = function default_parser(module) { return module.source; }; // 1st pass var parsed_assets = {}; // global paths to parsed asset paths var global_paths_to_parsed_asset_paths = {}; // define __webpack_public_path__ webpack variable // (resolves "ReferenceError: __webpack_public_path__ is not defined") var define_webpack_public_path = 'var __webpack_public_path__ = ' + JSON.stringify(options.assets_base_url) + ';\n'; var _loop = function () { if (_isArray) { if (_i >= _iterator.length) return 'break'; _ref = _iterator[_i++]; } else { _i = _iterator.next(); if (_i.done) return 'break'; _ref = _i.value; } var asset_type = _ref; // asset type settings var asset_type_settings = options.assets[asset_type]; // one can supply his own filter var filter = asset_type_settings.filter || default_filter; //.bind(this) // one can supply his own path parser var extract_asset_path = asset_type_settings.path || default_asset_path; //.bind(this) // one can supply his own parser var parser = asset_type_settings.parser || default_parser; //.bind(this) // guard agains typos, etc // for filter if (!asset_type_settings.filter) { log.debug('No filter specified for "' + asset_type + '" assets. Using a default one.'); } // for path parser if (!asset_type_settings.path) { log.debug('No path parser specified for "' + asset_type + '" assets. Using a default one.'); } // for parser if (!asset_type_settings.parser) { log.debug('No parser specified for "' + asset_type + '" assets. Using a default one.'); } log.debug('parsing assets of type "' + asset_type + '"'); // timer start var began_at = new Date().getTime(); // get real paths for all the files from this asset type json.modules // take just modules of this asset type .filter(function (module) { // check that this asset is of the asset type if (!filter(module, options.regular_expressions[asset_type], options, log)) { return false; } // guard against an empty source. if (!module.source) { log.error('Module "' + module.name + '" has no source. Maybe Webpack compilation of this module failed. Skipping this asset.'); return false; } // include this asset return true; }).reduce(function (set, module) { // determine asset real path var asset_path = extract_asset_path(module, options, log); // asset module source, or asset content (or whatever else) var parsed_asset = parser(module, options, log); log.trace('Adding asset "' + asset_path + '", module id ' + module.id + ' (in webpack-stats.json)'); // check for naming collisions (just in case) if (_helpers.exists(set[asset_path])) { log.error('-----------------------------------------------------------------'); log.error('Asset with path "' + asset_path + '" was overwritten because of path collision.'); log.error('Use the "filter" function of this asset type to narrow the results.'); log.error('Previous asset with this path:'); log.error(set[asset_path]); log.error('New asset with this path:'); log.error(parsed_asset); log.error('-----------------------------------------------------------------'); } // add this asset to the list // // also resolve "ReferenceError: __webpack_public_path__ is not defined". // because it may be a url-loaded resource (e.g. a font inside a style). set[asset_path] = define_webpack_public_path + _requireHacker2['default'].to_javascript_module_source(parsed_asset); // add path mapping global_paths_to_parsed_asset_paths[_path2['default'].resolve(options.project_path, asset_path)] = asset_path; // continue return set; }, parsed_assets); // timer stop log.debug(' time taken: ' + (new Date().getTime() - began_at) + ' ms'); }; // for each user specified asset type for (var _iterator = Object.keys(options.assets), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { var _ref; var _ret = _loop(); if (_ret === 'break') break; } // register a special require() hook for requiring() raw webpack modules var require_hook = _requireHacker2['default'].global_hook('webpack-module', function (required_path, module) { log.debug('require()ing "' + required_path + '"'); // if Webpack aliases are supplied if (options.alias) { // possibly alias the path var aliased_global_path = _common.alias_hook(required_path, module, options.project_path, options.alias, log); // if an alias is found if (aliased_global_path) { return _requireHacker2['default'].to_javascript_module_source(require(aliased_global_path)); } } // find an asset with this path // // the require()d path will be global path in case of the for..of require() loop // for the assets (the code a couple of screens below). // // (it can be anything in other cases (e.g. nested require() calls from the assets)) // if (_helpers.exists(global_paths_to_parsed_asset_paths[required_path])) { log.debug(' found in parsed assets'); return parsed_assets[global_paths_to_parsed_asset_paths[required_path]]; } log.debug(' not found in parsed assets, searching in webpack stats'); // find a webpack module which has a reason with this path var candidates = []; for (var _iterator2 = json.modules, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { var _ref2; if (_isArray2) { if (_i2 >= _iterator2.length) break; _ref2 = _iterator2[_i2++]; } else { _i2 = _iterator2.next(); if (_i2.done) break; _ref2 = _i2.value; } var _module2 = _ref2; for (var _iterator3 = _module2.reasons, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { var _ref3; if (_isArray3) { if (_i3 >= _iterator3.length) break; _ref3 = _iterator3[_i3++]; } else { _i3 = _iterator3.next(); if (_i3.done) break; _ref3 = _i3.value; } var reason = _ref3; if (reason.userRequest === required_path) { candidates.push(_module2); break; } } } // guard against ambiguity if (candidates.length === 1) { log.debug(' found in webpack stats, module id ' + candidates[0].id); // also resolve "ReferenceError: __webpack_public_path__ is not defined". // because it may be a url-loaded resource (e.g. a font inside a style). return define_webpack_public_path + candidates[0].source; } // if there are more than one candidate for this require()d path, // then try to guess which one is the one require()d if (candidates.length > 1) { log.debug(' More than a single candidate module was found in webpack stats for require()d path "' + required_path + '"'); for (var _iterator4 = candidates, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { var _ref4; if (_isArray4) { if (_i4 >= _iterator4.length) break; _ref4 = _iterator4[_i4++]; } else { _i4 = _iterator4.next(); if (_i4.done) break; _ref4 = _i4.value; } var candidate = _ref4; log.debug(' ', candidate); } // (loaders matter so the program can't simply throw them away from the required path) // // // tries to normalize a cryptic Webpack loader path // // into a regular relative file path // // https://webpack.github.io/docs/loaders.html // let filesystem_required_path = last(required_path // .replace(/^!!/, '') // .replace(/^!/, '') // .replace(/^-!/, '') // .split('!')) var fail = function fail() { throw new Error('More than a single candidate module was found in webpack stats for require()d path "' + required_path + '". Enable "debug: true" flag in webpack-isomorphic-tools configuration for more info.'); }; // https://webpack.github.io/docs/loaders.html var is_webpack_loader_path = required_path.indexOf('!') >= 0; // if it's a Webpack loader-powered path, the code gives up if (is_webpack_loader_path) { fail(); } // from here on it's either a filesystem path or an npm module path var is_a_global_path = function is_a_global_path(path) { return _helpers.starts_with(path, '/') || path.indexOf(':') > 0; }; var is_a_relative_path = function is_a_relative_path(path) { return _helpers.starts_with(path, './') || _helpers.starts_with(path, '../'); }; var is_relative_path = is_a_relative_path(required_path); var is_global_path = is_a_global_path(required_path); var is_npm_module_path = !is_relative_path && !is_global_path; // if it's a global path it can be resolved right away if (is_global_path) { return _requireHacker2['default'].to_javascript_module_source(require(required_path)); } // from here on it's either a relative filesystem path or an npm module path, // so it can be resolved against the require()ing file path (if it can be recovered). // `module.filename` here can be anything, not just a filesystem absolute path, // since some advanced require() hook trickery is involved. // therefore it will be parsed. // var requiring_file_path = module.filename.replace(/\.webpack-module$/, ''); // if it's a webpack loader-powered path, then extract the filesystem path from it if (requiring_file_path.indexOf('!') >= 0) { requiring_file_path = requiring_file_path.substring(requiring_file_path.lastIndexOf('!') + 1); } // make relative path global if (is_a_relative_path(requiring_file_path)) { requiring_file_path = _path2['default'].resolve(options.project_path, requiring_file_path); } // if `requiring_file_path` is a filesystem path (not an npm module path), // then the require()d path can possibly be resolved if (is_a_global_path(requiring_file_path)) { log.debug(' The module is being require()d from "' + requiring_file_path + '", so resolving the path against this file'); // if it's a relative path, can try to resolve it if (is_relative_path) { return _requireHacker2['default'].to_javascript_module_source(require(_path2['default'].resolve(requiring_file_path, '..', required_path))); } // if it's an npm module path (e.g. 'babel-runtime/core-js/object/assign'), // can try to require() it from the requiring asset path if (is_npm_module_path && is_a_global_path(module.filename)) { return _requireHacker2['default'].to_javascript_module_source(require(_requireHacker2['default'].resolve(required_path, module))); } } // if it's still here then it means it's either a fail(); } }); log.debug('compiling assets'); // timer start var began_at = new Date().getTime(); // evaluate parsed assets source code for (var _iterator5 = Object.keys(parsed_assets), _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { var _ref5; if (_isArray5) { if (_i5 >= _iterator5.length) break; _ref5 = _iterator5[_i5++]; } else { _i5 = _iterator5.next(); if (_i5.done) break; _ref5 = _i5.value; } var asset_path = _ref5; // set asset value log.debug('compiling asset "' + asset_path + '"'); output.assets[asset_path] = require(_path2['default'].resolve(options.project_path, asset_path)) // inside that require() call above // all the assets are resolved relative to this `module`, // which is irrelevant because they are all absolute filesystem paths. // // if in some of those assets a nested require() call is present // then it will be resolved relative to that asset folder. ; } // unmount the previously installed require() hook require_hook.unmount(); // timer stop log.debug(' time taken: ' + (new Date().getTime() - began_at) + ' ms'); } module.exports = exports['default']; //# sourceMappingURL=write assets.js.map