UNPKG

twreporter-react

Version:

React-Redux site for The Reporter Foundation in Taiwan

227 lines (190 loc) 7.84 kB
import path from 'path' import write_assets from './write assets' import notify_stats from './notify stats' import Log from './../tools/log' import { exists, clone, convert_from_camel_case, alias_properties_with_camel_case } from './../helpers' import { default_webpack_assets, normalize_options } from './../common' // a Webpack plugin export default function Webpack_isomorphic_tools_plugin(options) { // take the passed in options this.options = convert_from_camel_case(clone(options)) // add missing fields, etc normalize_options(this.options) // logging this.log = new Log('webpack-isomorphic-tools/plugin', { debug: this.options.debug }) // assets regular expressions (based on extensions). // will be used in loaders and in write_assets this.regular_expressions = {} // for each user defined asset type for (let asset_type of Object.keys(this.options.assets)) { const description = this.options.assets[asset_type] // create a regular expression for this file extension (or these file extensions) this.regular_expressions[asset_type] = description.regular_expression || Webpack_isomorphic_tools_plugin.regular_expression(description.extensions) } } // creates a regular expression for this file extension (or these file extensions) Webpack_isomorphic_tools_plugin.prototype.regular_expression = function(asset_type) { if (!exists(this.regular_expressions[asset_type])) { throw new Error(`There's no asset type "${asset_type}" defined in webpack-isomorphic-tools configuration. Perhaps you didn't spell it correctly.`) } return this.regular_expressions[asset_type] } // creates a regular expression for this file extension (or these file extensions) Webpack_isomorphic_tools_plugin.regular_expression = function(extensions) { if (!Array.isArray(extensions)) { throw new Error(`You were expected to pass a list of extensions (an array). Instead got: ${extensions}. Maybe you were looking for the instance method istead of the class method of this plugin?`) } let matcher if (extensions.length > 1) { matcher = `(${extensions.join('|')})` } else { matcher = extensions } return new RegExp(`\\.${matcher}$`) } // sets development mode flag to whatever was passed (or true if nothing was passed) // (development mode allows asset hot reloading when used with webpack-dev-server) Webpack_isomorphic_tools_plugin.prototype.development = function(flag) { // set development mode flag this.options.development = exists(flag) ? flag : true /* istanbul ignore else */ if (this.options.development) { this.log.debug('entering development mode') } else { this.log.debug('entering production mode') } // allows method chaining return this } // applies the plugin to the Webpack build Webpack_isomorphic_tools_plugin.prototype.apply = function(compiler) { // Webpack configuration const webpack_configuration = compiler.options // validate webpack configuration if (!webpack_configuration.context) { throw new Error('You must specify ".context" in your webpack configuration') } // project base path, required to output webpack-assets.json this.options.project_path = webpack_configuration.context // resolve webpack-assets.json file path const webpack_assets_path = path.resolve(this.options.project_path, this.options.webpack_assets_file_path) // resolve webpack-stats.json file path const webpack_stats_path = path.resolve(this.options.project_path, this.options.webpack_stats_file_path) // selfie const plugin = this // when all is done // https://github.com/webpack/docs/wiki/plugins compiler.plugin('done', function(stats) { plugin.log.debug('------------------- Started -------------------') const json = stats.toJson ({ context: webpack_configuration.context }) // output some info to the console if in development mode if (plugin.options.development) { // outputs stats info to the console // (only needed in development mode) notify_stats(stats, json, plugin.options.verbose) } // assets base path (on disk or on the network) // // (first search for the `devServer.publicPath` setting, // then fallback to the generic `publicPath`) // // (using `publicPath` from webpack stats here // as opposed to `webpack_configuration.output.publicPath` // because it is processed by webpack replacing things like `[hash]`) // const assets_base_url = (webpack_configuration.devServer && webpack_configuration.devServer.publicPath) ? webpack_configuration.devServer.publicPath : json.publicPath // write webpack-assets.json with assets info write_assets(json, { development : plugin.options.development, debug : plugin.options.debug, assets : plugin.options.assets, alias : plugin.options.alias, project_path : plugin.options.project_path, assets_base_url, webpack_assets_path : webpack_assets_path, webpack_stats_path : webpack_stats_path, output : default_webpack_assets(), regular_expressions : plugin.regular_expressions }, plugin.log) plugin.log.debug('------------------- Finished -------------------') }) } // a sample module source parser for webpack url-loader // (works for images, fonts, and i guess for everything else, should work for any file type) Webpack_isomorphic_tools_plugin.url_loader_parser = function(module, options, log) { return module.source } // a sample module source parser for webpack css-loader // (without css-loader "modules" feature support) Webpack_isomorphic_tools_plugin.css_loader_parser = function(module, options, log) { return module.source + '\n module.exports = module.exports.toString();' } // a sample module source parser for webpack css-loader // (with css-loader "modules" feature support) Webpack_isomorphic_tools_plugin.css_modules_loader_parser = function(module, options, log) { return module.source + '\n module.exports = exports.locals || {}; module.exports._style = exports.toString();' } // a filter for getting a css module when using it with style-loader // // in development mode there's webpack "style-loader", // so the module with module.name equal to the asset path is not what's needed // (because what that module does is it creates a <style/> tag on the page). // the module with the CSS styles is the one with a long name: Webpack_isomorphic_tools_plugin.style_loader_filter = function(module, regular_expression, options, log) { const css_loader = module.name.split('!')[0] return regular_expression.test(module.name) && // The paths below have the form of "/~/css-loader" // and not the form of "./~/css-loader" // because in some (non-standard) cases // Webpack project context can be set // not to project root folder. // // For a discussion see: // https://github.com/halt-hammerzeit/webpack-isomorphic-tools/pull/68 // (there the `context` is set to the "${project_root}/src" folder // so that the asset paths in `webpack-assets.json` wouldn't // contain the "./src" prefix and therefore they will be found // when require()d from code in "./target" // which is compiled with Babel from the "./src" folder) // // I personally don't compile sources on the server side, // so I haven't thought of better ways of doing all that. // (css_loader.indexOf('/~/css-loader') > 0 || css_loader.indexOf('/~/.npminstall/css-loader') > 0 || css_loader.indexOf('/~/.store/css-loader') > 0) } // extracts css style file path Webpack_isomorphic_tools_plugin.style_loader_path_extractor = function(module, options, log) { return module.name.slice(module.name.lastIndexOf('!') + 1) } // alias camel case for those who prefer it alias_properties_with_camel_case(Webpack_isomorphic_tools_plugin.prototype) alias_properties_with_camel_case(Webpack_isomorphic_tools_plugin)