diff --git a/README.md b/README.md index ddc97898652..f2436aea4ac 100644 --- a/README.md +++ b/README.md @@ -236,11 +236,72 @@ The env vars are: | npm run start | Starts the express server (requires env vars) | | npm run build | Builds the libs (all apps) (requires env vars) | -Example: Building and running a production instance of the admin app: +Example: Building and running a production instance of the AMO app: -``` -NODE_APP_INSTANCE=admin NODE_ENV=production npm run build && npm run start -``` +```` +NODE_APP_INSTANCE=amo NODE_ENV=production npm run build +NODE_APP_INSTANCE=amo NODE_ENV=production npm run start +```` + +To run the app locally in production mode you'll need to create a config file +that looks something like this. Name it exactly as `config/local-production-amo.js`. + +````js +import { apiStageHost, amoStageCDN } from './lib/shared'; + +module.exports = { + // Statics will be served by node. + staticHost: '', + // FIXME: sign-in isn't working. + // fxaConfig: 'local', + + // The node server host and port. + serverHost: '127.0.0.1', + serverPort: 3000, + + enableClientConsole: true, + apiHost: apiStageHost, + amoCDN: amoStageCDN, + + CSP: { + directives: { + connectSrc: [ + apiStageHost, + ], + scriptSrc: [ + "'self'", + 'https://www.google-analytics.com', + ], + styleSrc: ["'self'"], + imgSrc: [ + "'self'", + 'data:', + amoStageCDN, + 'https://www.google-analytics.com', + ], + mediaSrc: ["'self'"], + fontSrc: [ + "'self'", + 'data:', + amoStageCDN, + ], + }, + }, + + // This is needed to serve assets locally. + enableNodeStatics: true, + trackingEnabled: false, + // Do not send client side errors to Sentry. + publicSentryDsn: null, +}; +```` + +After this, re-build and restart using `npm run build` and `npm run start` +as documented above. +If you have used `localhost` before with a different configuration, +be sure to clear your cookies. + +**NOTE**: At this time, it's not possible to sign in using this approach. ## What version is deployed? diff --git a/bin/config-check.js b/bin/config-check.js index 9fa80344ea6..7a47f4477f5 100755 --- a/bin/config-check.js +++ b/bin/config-check.js @@ -20,15 +20,15 @@ if (!fs.statSync(configDir).isDirectory()) { } const disallowedFiles = fs.readdirSync(configDir) - // Disallow any local configs except for development configs. - .filter((name) => - name.startsWith('local') && !name.startsWith('local-development')) + // Disallow any local configs that could possibly pollute the tests. + .filter((name) => name === 'local.js' || name.startsWith('local-test')) .map((name) => path.join(configDir, name).replace(process.cwd(), '.')); if (disallowedFiles.length) { console.log(chalk.red( 'These local config files are not allowed because they might pollute ' + - 'the test environment. Prefix them with local-development- instead:')); + 'the test environment. Prefix them with local-development- or remove ' + + 'them:')); console.log(chalk.red(disallowedFiles.join('\n'))); process.exit(1); } diff --git a/config/default.js b/config/default.js index 87b2037783f..32e3c48aec4 100644 --- a/config/default.js +++ b/config/default.js @@ -16,7 +16,8 @@ const validAppNames = [ // Throw if the appName supplied is not valid. if (appName && !validAppNames.includes(appName)) { - throw new Error(`App ${appName} is not enabled`); + throw new Error( + `App "${appName}" is not enabled; valid app names: ${validAppNames}`); } diff --git a/karma.conf.js b/karma.conf.js index 4fbe5dd72f1..8e294212155 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -7,13 +7,12 @@ require('babel-register'); const fs = require('fs'); -const webpack = require('webpack'); -const config = require('config'); - -const getClientConfig = require('./src/core/utils').getClientConfig; +const webpackCommon = require('./webpack-common'); const webpackConfigProd = require('./webpack.prod.config.babel').default; -const clientConfig = getClientConfig(config); +const getPlugins = webpackCommon.getPlugins; +const getRules = webpackCommon.getRules; + const babelrc = fs.readFileSync('./.babelrc'); const babelQuery = JSON.parse(babelrc); @@ -24,16 +23,14 @@ const coverageReporters = [{ babelQuery.plugins.push(['istanbul', { include: 'src/**' }]); const newWebpackConfig = Object.assign({}, webpackConfigProd, { + devtool: 'inline-source-map', + module: { + rules: getRules({ babelQuery, bundleStylesWithJs: true }), + }, + output: undefined, + entry: undefined, plugins: [ - new webpack.DefinePlugin({ - CLIENT_CONFIG: JSON.stringify(clientConfig), - }), - // Replaces server config module with the subset clientConfig object. - new webpack.NormalModuleReplacementPlugin(/config$/, 'core/client/config.js'), - // Substitutes client only config. - new webpack.NormalModuleReplacementPlugin(/core\/logger$/, 'core/client/logger.js'), - // Use the browser's window for window. - new webpack.NormalModuleReplacementPlugin(/core\/window/, 'core/browserWindow.js'), + ...getPlugins({ excludeOtherAppLocales: false }), // Plugin to show any webpack warnings and prevent tests from running // Based on: https://gist.github.com/Stuk/6b574049435df532e905 function WebpackWarningPlugin() { @@ -69,52 +66,6 @@ const newWebpackConfig = Object.assign({}, webpackConfigProd, { }); }, ], - devtool: 'inline-source-map', - module: { - loaders: [ - { - test: /\.jsx?$/, - exclude: /node_modules/, - loader: 'babel', - query: babelQuery, - }, { - test: /\.css$/, - loader: 'style!css?importLoaders=2!postcss?outputStyle=expanded', - }, { - test: /\.scss$/, - loader: 'style!css?importLoaders=2!postcss!sass?outputStyle=expanded', - }, { - test: /\.svg$/, - loader: 'url?limit=10000&mimetype=image/svg+xml', - }, { - test: /\.jpg$/, - loader: 'url?limit=10000&mimetype=image/jpeg', - }, { - test: /\.png$/, - loader: 'url?limit=10000&mimetype=image/png', - }, { - test: /\.gif/, - loader: 'url?limit=10000&mimetype=image/gif', - }, { - test: /\.webm$/, - loader: 'url?limit=10000&mimetype=video/webm', - }, { - test: /\.mp4$/, - loader: 'url?limit=10000&mimetype=video/mp4', - }, { - test: /\.otf$/, - loader: 'url?limit=10000&mimetype=application/font-sfnt', - }, { - test: /\.woff$/, - loader: 'url?limit=10000&mimetype=application/font-woff', - }, { - test: /\.woff2$/, - loader: 'url?limit=10000&mimetype=application/font-woff2', - }, - ], - }, - output: undefined, - entry: undefined, }); const reporters = [ diff --git a/package.json b/package.json index cb066b3cfdc..dd3ba02880e 100644 --- a/package.json +++ b/package.json @@ -186,7 +186,7 @@ "dompurify": "0.8.9", "es6-error": "4.0.2", "express": "4.15.2", - "extract-text-webpack-plugin": "1.0.1", + "extract-text-webpack-plugin": "2.1.0", "fastclick": "1.0.6", "helmet": "3.6.0", "humps": "2.0.0", @@ -229,7 +229,7 @@ "babel-core": "^6.24.1", "babel-eslint": "^7.2.3", "babel-gettext-extractor": "git+https://github.com/muffinresearch/babel-gettext-extractor.git#0d39d3882bc846e7dcb6c9ff6463896c96920ce6", - "babel-loader": "^6.4.1", + "babel-loader": "^7.0.0", "babel-plugin-istanbul": "^4.1.3", "babel-plugin-react-transform": "^2.0.2", "babel-plugin-transform-class-properties": "^6.24.1", @@ -285,17 +285,18 @@ "semver": "^5.3.0", "shelljs": "^0.7.7", "sinon": "^2.2.0", - "sri-stats-webpack-plugin": "^0.7.3", "style-loader": "^0.17.0", "stylelint": "^7.10.1", "stylelint-config-standard": "^16.0.0", "supertest": "^3.0.0", "supertest-as-promised": "^4.0.2", "svg-url-loader": "^2.0.2", + "tmp": "^0.0.31", "tosource": "^1.0.0", - "webpack": "^1.14.0", + "webpack": "^2.5.1", "webpack-dev-middleware": "^1.10.2", "webpack-dev-server": "^2.4.5", - "webpack-hot-middleware": "^2.18.0" + "webpack-hot-middleware": "^2.18.0", + "webpack-subresource-integrity": "^1.0.0-rc.1" } } diff --git a/src/core/client/base.js b/src/core/client/base.js index b622ae2890f..918cc9fb8a6 100644 --- a/src/core/client/base.js +++ b/src/core/client/base.js @@ -78,7 +78,7 @@ export default function makeClient(routes, createStore) { try { if (locale !== langToLocale(config.get('defaultLang'))) { // eslint-disable-next-line max-len, global-require, import/no-dynamic-require - require(`bundle?name=[name]-i18n-[folder]!../../locale/${locale}/${appName}.js`)(renderApp); + require(`bundle-loader?name=[name]-i18n-[folder]!../../locale/${locale}/${appName}.js`)(renderApp); } else { renderApp({}); } diff --git a/src/core/server/sriDataPlugin.js b/src/core/server/sriDataPlugin.js new file mode 100644 index 00000000000..9aebd4b9dd0 --- /dev/null +++ b/src/core/server/sriDataPlugin.js @@ -0,0 +1,36 @@ +// This is a webpack plugin to expose the data generated by SriPlugin. +// See webpack.prod.config.babel.js +import fs from 'fs'; + +import { oneLine } from 'common-tags'; + +export default class SriDataPlugin { + constructor({ saveAs } = {}) { + if (!saveAs) { + throw new Error('The saveAs parameter cannot be empty'); + } + this.saveAs = saveAs; + } + + apply(compiler) { + compiler.plugin('done', (stats) => { + const sriStats = {}; + try { + Object.keys(stats.compilation.assets).forEach((baseName) => { + const asset = stats.compilation.assets[baseName]; + if (!asset.integrity) { + throw new Error( + oneLine`The integrity property is falsey for + asset ${baseName}; Is the webpack-subresource-integrity + plugin installed and enabled?`); + } + sriStats[baseName] = asset.integrity; + }); + + fs.writeFileSync(this.saveAs, JSON.stringify(sriStats)); + } catch (error) { + stats.compilation.errors.push(error); + } + }); + } +} diff --git a/tests/server/TestSriDataPlugin.js b/tests/server/TestSriDataPlugin.js new file mode 100644 index 00000000000..b9c2be103c3 --- /dev/null +++ b/tests/server/TestSriDataPlugin.js @@ -0,0 +1,116 @@ +import fs from 'fs'; +import path from 'path'; + +import { assert } from 'chai'; +import webpack from 'webpack'; +import SriPlugin from 'webpack-subresource-integrity'; +import tmp from 'tmp'; + +import SriDataPlugin from 'core/server/sriDataPlugin'; + +describe('SriDataPlugin', () => { + let distDir; + let srcDir; + let tempDir; + + beforeEach(() => { + tempDir = tmp.dirSync({ unsafeCleanup: true }); + srcDir = path.join(tempDir.name, 'src'); + distDir = path.join(tempDir.name, 'dist'); + + fs.mkdirSync(srcDir); + fs.mkdirSync(distDir); + + fs.writeFileSync(path.join(srcDir, 'app.js'), '// some JS code'); + }); + + afterEach(() => { + tempDir.removeCallback(); + }); + + function compile({ + entry = {}, includeSriPlugin = true, + } = {}) { + const sriFile = path.join(distDir, 'sri.json'); + + const plugins = []; + if (includeSriPlugin) { + plugins.push(new SriPlugin({ hashFuncNames: ['sha512'] })); + } + plugins.push(new SriDataPlugin({ saveAs: sriFile })); + + const compiler = webpack({ + entry: { + app: path.join(srcDir, 'app'), + ...entry, + }, + output: { + crossOriginLoading: 'anonymous', + path: path.join(tempDir.name, 'dist'), + filename: '[name].js', + chunkFilename: '[name].js', + }, + plugins, + }); + + return new Promise((resolve, reject) => compiler.run((error, stats) => { + if (error) { + return reject(error); + } + if (stats.compilation.errors && stats.compilation.errors.length) { + return reject(new Error( + `Webpack errors: ${stats.compilation.errors.join('; ')}` + )); + } + return resolve({ + stats, + sriData: JSON.parse(fs.readFileSync(sriFile)), + }); + })); + } + + it('handles a single asset file', () => { + return compile({ + entry: { + app: path.join(srcDir, 'app'), + }, + }) + .then(({ sriData }) => { + assert.match(sriData['app.js'], /^sha512-.*/); + }); + }); + + it('handles multiple asset files', () => { + return compile({ + entry: { + app: path.join(srcDir, 'app'), + app2: path.join(srcDir, 'app'), + }, + }) + .then(({ sriData }) => { + assert.match(sriData['app.js'], /^sha512-.*/); + assert.match(sriData['app2.js'], /^sha512-.*/); + }); + }); + + it('requires the SriPlugin', () => { + return compile({ + entry: { + app: path.join(srcDir, 'app'), + }, + includeSriPlugin: false, + }) + .then( + () => assert.fail(null, null, 'Unexpected success'), + (error) => { + assert.match(error.message, + /The integrity property is falsey for asset app\.js/); + } + ); + }); + + it('requires a saveAs parameter', () => { + assert.throws( + () => new SriDataPlugin(), /saveAs parameter cannot be empty/); + }); +}); diff --git a/webpack-common.js b/webpack-common.js new file mode 100644 index 00000000000..69d56ba86cf --- /dev/null +++ b/webpack-common.js @@ -0,0 +1,139 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import config from 'config'; +import ExtractTextPlugin from 'extract-text-webpack-plugin'; +import webpack from 'webpack'; + +import { getClientConfig } from 'core/utils'; + +// Common options for URL loaders (i.e. derivatives of file-loader). +const urlLoaderOptions = { + // If a media file is less than this size in bytes, it will be linked as a data: URL. + // Otherwise it will be linked as a separate file URL. + limit: 10000, +}; + +export function getRules({ babelQuery, bundleStylesWithJs = false } = {}) { + let styleRules; + + if (bundleStylesWithJs) { + // In development, we bundle styles with the JS. + styleRules = [ + { + test: /\.css$/, + use: [ + { loader: 'style-loader' }, + { loader: 'css-loader', options: { importLoaders: 2 } }, + { loader: 'postcss-loader', options: { outputStyle: 'expanded' } }, + ], + }, { + test: /\.scss$/, + use: [ + { loader: 'style-loader' }, + { loader: 'css-loader', options: { importLoaders: 2 } }, + { loader: 'postcss-loader' }, + { loader: 'sass-loader', options: { outputStyle: 'expanded' } }, + ], + }, + ]; + } else { + // In production, we create a separate CSS bundle rather than + // include styles with the JS bundle. This lets the style bundle + // load in parallel. + styleRules = [ + { + test: /\.css$/, + loader: ExtractTextPlugin.extract({ + fallback: 'style-loader', + use: [ + { + loader: 'css-loader', + options: { importLoaders: 2, sourceMap: true }, + }, + { + loader: 'postcss-loader', + options: { + outputStyle: 'expanded', + sourceMap: true, + sourceMapContents: true, + }, + }, + ], + }), + }, { + test: /\.scss$/, + loader: ExtractTextPlugin.extract({ + fallback: 'style-loader', + use: [ + { + loader: 'css-loader', + options: { importLoaders: 2, sourceMap: true }, + }, + { loader: 'postcss-loader' }, + { + loader: 'sass-loader', + options: { + outputStyle: 'expanded', + sourceMap: true, + sourceMapContents: true, + }, + }, + ], + }), + }, + ]; + } + + return [ + { + test: /\.jsx?$/, + exclude: /node_modules/, + loader: 'babel-loader', + query: babelQuery, + }, + ...styleRules, + { + test: /\.svg$/, + use: [{ loader: 'svg-url-loader', options: urlLoaderOptions }], + }, { + test: /\.(jpg|png|gif|webm|mp4|otf|woff|woff2)$/, + use: [{ loader: 'url-loader', options: urlLoaderOptions }], + }, + ]; +} + +export function getPlugins({ excludeOtherAppLocales = true } = {}) { + const appName = config.get('appName'); + const clientConfig = getClientConfig(config); + + const plugins = [ + new webpack.DefinePlugin({ + CLIENT_CONFIG: JSON.stringify(clientConfig), + 'process.env.NODE_ENV': JSON.stringify('production'), + }), + // Since the NodeJS code does not run from a webpack bundle, here + // are a few replacements that affect only the client side bundle. + // + // This replaces the config with a new module that has sensitive, + // server-only keys removed. + new webpack.NormalModuleReplacementPlugin( + /config$/, 'core/client/config.js'), + // This replaces the logger with a more lightweight logger for the client. + new webpack.NormalModuleReplacementPlugin( + /core\/logger$/, 'core/client/logger.js'), + // This swaps the server side window object with a standard browser window. + new webpack.NormalModuleReplacementPlugin( + /core\/window/, 'core/browserWindow.js'), + ]; + + if (excludeOtherAppLocales) { + plugins.push( + // This allow us to exclude locales for other apps being built. + new webpack.ContextReplacementPlugin( + /locale$/, + new RegExp(`^\\.\\/.*?\\/${appName}\\.js$`) + ), + ); + } + + return plugins; +} diff --git a/webpack.dev.config.babel.js b/webpack.dev.config.babel.js index 6ab08a377b3..90e2e1549ec 100644 --- a/webpack.dev.config.babel.js +++ b/webpack.dev.config.babel.js @@ -7,13 +7,11 @@ import config from 'config'; import webpack from 'webpack'; import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin'; -import { getClientConfig } from 'core/utils'; - +import { getPlugins, getRules } from './webpack-common'; import webpackConfig from './webpack.prod.config.babel'; import webpackIsomorphicToolsConfig from './src/core/server/webpack-isomorphic-tools-config'; -const clientConfig = getClientConfig(config); const localDevelopment = config.util.getEnv('NODE_ENV') === 'development'; const webpackIsomorphicToolsPlugin = @@ -32,7 +30,8 @@ const babelDevPlugins = [['react-transform', { }]]; const BABEL_QUERY = Object.assign({}, babelrcObject, { - plugins: localDevelopment ? babelPlugins.concat(babelDevPlugins) : babelPlugins, + plugins: localDevelopment ? + babelPlugins.concat(babelDevPlugins) : babelPlugins, }); const webpackHost = config.get('webpackServerHost'); @@ -55,6 +54,9 @@ for (const app of appsBuildList) { export default Object.assign({}, webpackConfig, { devtool: 'inline-source-map', + devServer: { + progress: true, + }, context: path.resolve(__dirname), entry: entryPoints, output: Object.assign({}, webpackConfig.output, { @@ -64,64 +66,10 @@ export default Object.assign({}, webpackConfig, { publicPath: `//${webpackHost}:${webpackPort}/`, }), module: { - loaders: [ - { - test: /\.jsx?$/, - exclude: /node_modules/, - loader: 'babel', - query: BABEL_QUERY, - }, { - test: /\.css$/, - loader: 'style!css?importLoaders=2!postcss?outputStyle=expanded', - }, { - test: /\.scss$/, - loader: 'style!css?importLoaders=2!postcss!sass?outputStyle=expanded', - }, { - test: /\.svg$/, - loader: 'svg-url?limit=10000', - }, { - test: /\.jpg$/, - loader: 'url?limit=10000&mimetype=image/jpeg', - }, { - test: /\.png$/, - loader: 'url?limit=10000&mimetype=image/png', - }, { - test: /\.gif/, - loader: 'url?limit=10000&mimetype=image/gif', - }, { - test: /\.webm$/, - loader: 'url?limit=10000&mimetype=video/webm', - }, { - test: /\.mp4$/, - loader: 'url?limit=10000&mimetype=video/mp4', - }, { - test: /\.otf$/, - loader: 'url?limit=10000&mimetype=application/font-sfnt', - }, { - test: /\.woff$/, - loader: 'url?limit=10000&mimetype=application/font-woff', - }, { - test: /\.woff2$/, - loader: 'url?limit=10000&mimetype=application/font-woff2', - }, - ], + rules: getRules({ babelQuery: BABEL_QUERY, bundleStylesWithJs: true }), }, plugins: [ - new webpack.DefinePlugin({ - CLIENT_CONFIG: JSON.stringify(clientConfig), - 'process.env.NODE_ENV': JSON.stringify('production'), - }), - // Replaces server config module with the subset clientConfig object. - new webpack.NormalModuleReplacementPlugin(/config$/, 'core/client/config.js'), - // This allow us to exclude locales for other apps being built. - new webpack.ContextReplacementPlugin( - /locale$/, - new RegExp(`^\\.\\/.*?\\/${appName}\\.js$`) - ), - // Substitutes client only config. - new webpack.NormalModuleReplacementPlugin(/core\/logger$/, 'core/client/logger.js'), - // Use the browser's window for window. - new webpack.NormalModuleReplacementPlugin(/core\/window/, 'core/browserWindow.js'), + ...getPlugins(), new webpack.HotModuleReplacementPlugin(), new webpack.IgnorePlugin(/webpack-stats\.json$/), webpackIsomorphicToolsPlugin.development(), diff --git a/webpack.l10n.config.babel.js b/webpack.l10n.config.babel.js index c6e7a8460b5..66b428c988d 100644 --- a/webpack.l10n.config.babel.js +++ b/webpack.l10n.config.babel.js @@ -5,6 +5,7 @@ import chalk from 'chalk'; import config from 'config'; import webpack from 'webpack'; +import { getRules } from './webpack-common'; import webpackConfig from './webpack.prod.config.babel'; @@ -65,16 +66,14 @@ const BABEL_QUERY = Object.assign({}, babelrcObject, { plugins: babelPlugins.concat(babelL10nPlugins), }); -const newLoaders = webpackConfig.module.loaders.slice(0); -// Assumes the js loader is the first one. -newLoaders[0].query = BABEL_QUERY; - export default Object.assign({}, webpackConfig, { entry: { [appName]: `src/${appName}/client` }, module: { - loaders: newLoaders, + rules: getRules({ babelQuery: BABEL_QUERY }), }, plugins: [ + // Don't generate modules for locale files. new webpack.IgnorePlugin(new RegExp(`locale\\/.*\\/${appName}\\.js$`)), - ].concat(webpackConfig.plugins), + ...webpackConfig.plugins, + ], }); diff --git a/webpack.prod.config.babel.js b/webpack.prod.config.babel.js index abbf86074af..f02b1a9ae15 100644 --- a/webpack.prod.config.babel.js +++ b/webpack.prod.config.babel.js @@ -4,17 +4,15 @@ import path from 'path'; import autoprefixer from 'autoprefixer'; import config from 'config'; import ExtractTextPlugin from 'extract-text-webpack-plugin'; -import SriStatsPlugin from 'sri-stats-webpack-plugin'; +import SriPlugin from 'webpack-subresource-integrity'; import webpack from 'webpack'; import WebpackIsomorphicToolsPlugin from 'webpack-isomorphic-tools/plugin'; -import { getClientConfig } from 'core/utils'; - +import SriDataPlugin from './src/core/server/sriDataPlugin'; +import { getPlugins, getRules } from './webpack-common'; import webpackIsomorphicToolsConfig from './src/core/server/webpack-isomorphic-tools-config'; -const clientConfig = getClientConfig(config); - const appName = config.get('appName'); const appsBuildList = appName ? [appName] : config.get('validAppNames'); @@ -27,89 +25,36 @@ for (const app of appsBuildList) { const settings = { devtool: 'source-map', context: path.resolve(__dirname), - progress: true, entry: entryPoints, output: { + crossOriginLoading: 'anonymous', path: path.join(__dirname, 'dist'), filename: '[name]-[chunkhash].js', chunkFilename: '[name]-[chunkhash].js', publicPath: config.has('staticHost') ? `${config.get('staticHost')}/` : '/', }, module: { - loaders: [ - { - test: /\.jsx?$/, - exclude: /node_modules/, - loader: 'babel', - }, { - test: /\.css$/, - loader: ExtractTextPlugin.extract('style', 'css?importLoaders=2&sourceMap!postcss?outputStyle=expanded&sourceMap=true&sourceMapContents=true'), - }, { - test: /\.scss$/, - loader: ExtractTextPlugin.extract('style', 'css?importLoaders=2&sourceMap!postcss!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true'), - }, { - test: /\.svg$/, - loader: 'svg-url?limit=10000', - }, { - test: /\.jpg$/, - loader: 'url?limit=10000&mimetype=image/jpeg', - }, { - test: /\.png$/, - loader: 'url?limit=10000&mimetype=image/png', - }, { - test: /\.gif/, - loader: 'url?limit=10000&mimetype=image/gif', - }, { - test: /\.webm$/, - loader: 'url?limit=10000&mimetype=video/webm', - }, { - test: /\.mp4$/, - loader: 'url?limit=10000&mimetype=video/mp4', - }, { - test: /\.otf$/, - loader: 'url?limit=10000&mimetype=application/font-sfnt', - }, { - test: /\.woff$/, - loader: 'url?limit=10000&mimetype=application/font-woff', - }, { - test: /\.woff2$/, - loader: 'url?limit=10000&mimetype=application/font-woff2', - }, - ], + rules: getRules(), }, plugins: [ - new webpack.DefinePlugin({ - CLIENT_CONFIG: JSON.stringify(clientConfig), - 'process.env.NODE_ENV': JSON.stringify('production'), - }), - // Replaces server config module with the subset clientConfig object. - new webpack.NormalModuleReplacementPlugin(/config$/, 'core/client/config.js'), - // Substitutes client only config. - new webpack.NormalModuleReplacementPlugin(/core\/logger$/, 'core/client/logger.js'), - // Use the browser's window for window. - new webpack.NormalModuleReplacementPlugin(/core\/window/, 'core/browserWindow.js'), - // This allow us to exclude locales for other apps being built. - new webpack.ContextReplacementPlugin( - /locale$/, - new RegExp(`^\\.\\/.*?\\/${appName}\\.js$`) - ), - new ExtractTextPlugin('[name]-[contenthash].css', { allChunks: true }), - new SriStatsPlugin({ - algorithm: 'sha512', - write: true, - saveAs: path.join(__dirname, 'dist/sri.json'), + ...getPlugins(), + new ExtractTextPlugin({ + filename: '[name]-[contenthash].css', + allChunks: true, }), // optimizations - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurenceOrderPlugin(), new webpack.optimize.UglifyJsPlugin({ + sourceMap: true, comments: false, compress: { drop_console: true, - warnings: false, }, }), new WebpackIsomorphicToolsPlugin(webpackIsomorphicToolsConfig), + new SriPlugin({ hashFuncNames: ['sha512'] }), + new SriDataPlugin({ + saveAs: path.join(__dirname, 'dist', 'sri.json'), + }), // This function helps ensure we do bail if a compilation error // is encountered since --bail doesn't cause the build to fail with // uglify errors. @@ -128,19 +73,26 @@ const settings = { alias: { 'normalize.css': 'normalize.css/normalize.css', }, - root: [ + modules: [ path.resolve(__dirname), path.resolve('./src'), + 'node_modules', ], - modulesDirectories: ['node_modules'], - extensions: ['', '.js', '.jsx'], + extensions: ['.js', '.jsx'], }, }; if (config.get('enablePostCssLoader')) { - settings.postcss = [ - autoprefixer({ browsers: ['last 2 versions'] }), - ]; + settings.plugins.push( + new webpack.LoaderOptionsPlugin({ + options: { + context: path.resolve(__dirname), + postcss: [ + autoprefixer({ browsers: ['last 2 versions'] }), + ], + }, + }) + ); } export default settings; diff --git a/yarn.lock b/yarn.lock index 473e2c41755..517f80bf34f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,6 +24,12 @@ accepts@1.3.3, accepts@~1.3.3: mime-types "~2.1.11" negotiator "0.6.1" +acorn-dynamic-import@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" + dependencies: + acorn "^4.0.3" + acorn-globals@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" @@ -40,15 +46,15 @@ acorn@^1.0.3: version "1.2.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014" -acorn@^3.0.0, acorn@^3.0.4: +acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^4.0.4: +acorn@^4.0.3, acorn@^4.0.4: version "4.0.11" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0" -acorn@^5.0.1: +acorn@^5.0.0, acorn@^5.0.1: version "5.0.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d" @@ -56,11 +62,11 @@ after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" -ajv-keywords@^1.0.0: +ajv-keywords@^1.0.0, ajv-keywords@^1.1.1: version "1.5.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" -ajv@^4.7.0, ajv@^4.9.1: +ajv@^4.11.2, ajv@^4.7.0, ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: @@ -210,6 +216,14 @@ asap@~2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f" +asn1.js@^4.0.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.1.tgz#48ba240b45a9280e94748990ba597d216617fd40" + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" @@ -244,23 +258,19 @@ async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" -async@1.x, async@^1.3.0, async@^1.4.0, async@^1.5.0, async@^1.5.2: +async@1.x, async@^1.4.0, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^0.9.0, async@~0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - -async@^2.1.5: +async@^2.1.2, async@^2.1.5: version "2.4.0" resolved "https://registry.yarnpkg.com/async/-/async-2.4.0.tgz#4990200f18ea5b837c2cc4f8c031a6985c385611" dependencies: lodash "^4.14.0" -async@~0.2.6: - version "0.2.10" - resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" +async@~0.9.0: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" asynckit@^0.4.0: version "0.4.0" @@ -472,14 +482,13 @@ babel-helpers@^6.24.1: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-loader@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-6.4.1.tgz#0b34112d5b0748a8dcdbf51acf6f9bd42d50b8ca" +babel-loader@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.0.0.tgz#2e43a66bee1fff4470533d0402c8a4532fafbaf7" dependencies: find-cache-dir "^0.1.1" - loader-utils "^0.2.16" + loader-utils "^1.0.2" mkdirp "^0.5.1" - object-assign "^4.0.1" babel-messages@^6.23.0: version "6.23.0" @@ -1036,6 +1045,10 @@ bluebird@^3.3.0, bluebird@^3.3.1: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + body-parser@^1.16.1: version "1.17.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.1.tgz#75b3bc98ddd6e7e0d8ffe750dfaca5c66993fa47" @@ -1082,15 +1095,58 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" -browserify-aes@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-0.4.0.tgz#067149b668df31c4b58533e02d01e806d8608e2c" +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.0.6.tgz#5e7725dbdef1fd5930d4ebab48567ce451c48a0a" + dependencies: + buffer-xor "^1.0.2" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + inherits "^2.0.1" + +browserify-cipher@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd" + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" inherits "^2.0.1" + parse-asn1 "^5.0.0" browserify-zlib@^0.1.4: version "0.1.4" @@ -1109,7 +1165,11 @@ buffer-shims@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" -buffer@^4.9.0: +buffer-xor@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + +buffer@^4.3.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" dependencies: @@ -1281,7 +1341,7 @@ chokidar-cli@^1.2.0: shell-quote "^1.4.3" yargs "^3.7.2" -chokidar@^1.0.0, chokidar@^1.0.1, chokidar@^1.4.1, chokidar@^1.5.0, chokidar@^1.6.0: +chokidar@^1.0.1, chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.5.0, chokidar@^1.6.0: version "1.6.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2" dependencies: @@ -1296,6 +1356,12 @@ chokidar@^1.0.0, chokidar@^1.0.1, chokidar@^1.4.1, chokidar@^1.5.0, chokidar@^1. optionalDependencies: fsevents "^1.0.0" +cipher-base@^1.0.0, cipher-base@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.3.tgz#eeabf194419ce900da3018c207d212f2a6df0a07" + dependencies: + inherits "^2.0.1" + circular-json@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" @@ -1622,6 +1688,29 @@ coveralls@~2.11.2: minimist "1.2.0" request "2.79.0" +create-ecdh@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.2.tgz#51210062d7bb7479f6c65bb41a92208b1d61abad" + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + ripemd160 "^1.0.0" + sha.js "^2.3.6" + +create-hmac@^1.1.0, create-hmac@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.4.tgz#d3fb4ba253eb8b3f56e39ea2fbcb8af747bd3170" + dependencies: + create-hash "^1.1.0" + inherits "^2.0.1" + create-react-class@^15.5.x: version "15.5.2" resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.2.tgz#6a8758348df660b88326a0e764d569f274aad681" @@ -1642,14 +1731,20 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" -crypto-browserify@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.3.0.tgz#b9fc75bb4a0ed61dcf1cd5dae96eb30c9c3e506c" +crypto-browserify@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522" dependencies: - browserify-aes "0.4.0" - pbkdf2-compat "2.0.1" - ripemd160 "0.2.0" - sha.js "2.2.6" + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" css-color-names@0.0.3: version "0.0.3" @@ -1930,6 +2025,13 @@ depd@1.1.0, depd@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" @@ -1948,6 +2050,14 @@ diff@3.2.0, diff@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" +diffie-hellman@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + dns-prefetch-control@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz#60ddb457774e178f1f9415f0cabb0e85b0b300b2" @@ -2074,6 +2184,18 @@ electron-to-chromium@^1.2.7: version "1.3.9" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.9.tgz#db1cba2a26aebcca2f7f5b8b034554468609157d" +elliptic@^6.0.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -2127,13 +2249,14 @@ engine.io@1.8.3: engine.io-parser "1.3.2" ws "1.1.2" -enhanced-resolve@~0.9.0: - version "0.9.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" +enhanced-resolve@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz#9f4b626f577245edcf4b2ad83d86e17f4f421dec" dependencies: graceful-fs "^4.1.2" - memory-fs "^0.2.0" - tapable "^0.1.8" + memory-fs "^0.4.0" + object-assign "^4.0.1" + tapable "^0.2.5" ent@~2.2.0: version "2.2.0" @@ -2443,6 +2566,12 @@ eventsource@0.1.6: dependencies: original ">=0.0.5" +evp_bytestokey@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz#497b66ad9fef65cd7c08a6180824ba1476b66e53" + dependencies: + create-hash "^1.1.1" + execall@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73" @@ -2531,12 +2660,13 @@ extglob@^0.3.1: dependencies: is-extglob "^1.0.0" -extract-text-webpack-plugin@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-1.0.1.tgz#c95bf3cbaac49dc96f1dc6e072549fbb654ccd2c" +extract-text-webpack-plugin@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-2.1.0.tgz#69315b885f876dbf96d3819f6a9f1cca7aebf159" dependencies: - async "^1.5.0" - loader-utils "^0.2.3" + ajv "^4.11.2" + async "^2.1.2" + loader-utils "^1.0.2" webpack-sources "^0.1.0" extsprintf@1.0.2: @@ -3041,6 +3171,12 @@ has@^1.0.1: dependencies: function-bind "^1.0.2" +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.0.3.tgz#1332ff00156c0a0ffdd8236013d07b77a0451573" + dependencies: + inherits "^2.0.1" + hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" @@ -3091,6 +3227,14 @@ history@^2.1.2: query-string "^3.0.0" warning "^2.0.0" +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" @@ -3317,10 +3461,6 @@ inquirer@^0.12.0: strip-ansi "^3.0.0" through "^2.3.6" -interpret@^0.6.4: - version "0.6.6" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b" - interpret@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" @@ -3705,7 +3845,7 @@ json5@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json5/-/json5-0.4.0.tgz#054352e4c4c80c86c0923877d449de176a732c8d" -json5@^0.5.0: +json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -3919,6 +4059,10 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +loader-runner@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" + loader-utils@0.2.16: version "0.2.16" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d" @@ -3928,7 +4072,7 @@ loader-utils@0.2.16: json5 "^0.5.0" object-assign "^4.0.1" -loader-utils@^0.2.11, loader-utils@^0.2.16, loader-utils@^0.2.3, loader-utils@^0.2.5, loader-utils@~0.2.5: +loader-utils@^0.2.16, loader-utils@^0.2.5, loader-utils@~0.2.5: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" dependencies: @@ -4170,18 +4314,7 @@ media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" -memory-fs@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" - -memory-fs@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20" - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@~0.4.1: +memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" dependencies: @@ -4229,6 +4362,13 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" +miller-rabin@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.0.tgz#4a62fb1d42933c05583982f4c716f6fb9e6c6d3d" + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + "mime-db@>= 1.27.0 < 2", mime-db@~1.27.0: version "1.27.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" @@ -4253,6 +4393,10 @@ minimalistic-assert@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + "minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@~3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" @@ -4390,16 +4534,16 @@ node-gyp@^3.3.1: tar "^2.0.0" which "1" -node-libs-browser@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-0.7.0.tgz#3e272c0819e308935e26674408d7af0e1491b83b" +node-libs-browser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646" dependencies: assert "^1.1.1" browserify-zlib "^0.1.4" - buffer "^4.9.0" + buffer "^4.3.0" console-browserify "^1.1.0" constants-browserify "^1.0.0" - crypto-browserify "3.3.0" + crypto-browserify "^3.11.0" domain-browser "^1.1.1" events "^1.0.0" https-browserify "0.0.1" @@ -4612,7 +4756,7 @@ opn@4.0.2: object-assign "^4.0.1" pinkie-promise "^2.0.0" -optimist@^0.6.1, optimist@~0.6.0: +optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" dependencies: @@ -4679,6 +4823,16 @@ pako@~0.2.0: version "0.2.9" resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" +parse-asn1@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -4764,9 +4918,11 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -pbkdf2-compat@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288" +pbkdf2@^3.0.3: + version "3.0.9" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.9.tgz#f2c4b25a600058b3c3773c086c37dbbee1ffe693" + dependencies: + create-hmac "^1.1.2" performance-now@^0.2.0: version "0.2.0" @@ -5213,6 +5369,16 @@ pseudomap@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" +public-encrypt@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6" + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -5269,6 +5435,10 @@ randomatic@^1.1.3: is-number "^2.0.2" kind-of "^3.0.2" +randombytes@^2.0.0, randombytes@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.3.tgz#674c99760901c3c4112771a31e521dc349cc09ec" + range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -5800,9 +5970,9 @@ rimraf@~2.4.0: dependencies: glob "^6.0.1" -ripemd160@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-0.2.0.tgz#2bf198bde167cacfa51c0a928e84b68bbe171fce" +ripemd160@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-1.0.1.tgz#93a4bbd4942bc574b69a8fa57c71de10ecca7d6e" run-async@^0.1.0: version "0.1.0" @@ -5942,9 +6112,11 @@ setprototypeof@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" -sha.js@2.2.6: - version "2.2.6" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba" +sha.js@^2.3.6: + version "2.4.8" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f" + dependencies: + inherits "^2.0.1" shallow-clone@^0.1.2: version "0.1.2" @@ -6085,6 +6257,10 @@ source-list-map@^0.1.7, source-list-map@~0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" +source-list-map@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1" + source-map-support@^0.4.2: version "0.4.15" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" @@ -6171,12 +6347,6 @@ sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" -sri-stats-webpack-plugin@^0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/sri-stats-webpack-plugin/-/sri-stats-webpack-plugin-0.7.3.tgz#2051a34356857b22bbf7c57beac7482647dbe919" - dependencies: - webpack-custom-stats-patch "^0.3.0" - sshpk@^1.7.0: version "1.13.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c" @@ -6493,9 +6663,9 @@ table@^4.0.1: slice-ansi "0.0.4" string-width "^2.0.0" -tapable@^0.1.8, tapable@~0.1.8: - version "0.1.10" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4" +tapable@^0.2.5, tapable@~0.2.5: + version "0.2.6" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.6.tgz#206be8e188860b514425375e6f1ae89bfb01fd8d" tar-pack@^3.4.0: version "3.4.0" @@ -6564,7 +6734,7 @@ timers-browserify@^2.0.2: dependencies: setimmediate "^1.0.4" -tmp@0.0.31, tmp@0.0.x: +tmp@0.0.31, tmp@0.0.x, tmp@^0.0.31: version "0.0.31" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" dependencies: @@ -6667,7 +6837,7 @@ ua-parser-js@0.7.12, ua-parser-js@^0.7.9: version "0.7.12" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb" -uglify-js@^2.6, uglify-js@^2.7.0: +uglify-js@^2.6, uglify-js@^2.7.0, uglify-js@^2.8.5: version "2.8.22" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0" dependencies: @@ -6676,15 +6846,6 @@ uglify-js@^2.6, uglify-js@^2.7.0: optionalDependencies: uglify-to-browserify "~1.0.0" -uglify-js@~2.7.3: - version "2.7.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" - dependencies: - async "~0.2.6" - source-map "~0.5.1" - uglify-to-browserify "~1.0.0" - yargs "~3.10.0" - uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -6837,12 +6998,12 @@ warning@^3.0.0: dependencies: loose-envify "^1.0.0" -watchpack@^0.2.1: - version "0.2.9" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-0.2.9.tgz#62eaa4ab5e5ba35fdfc018275626e3c0f5e3fb0b" +watchpack@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87" dependencies: - async "^0.9.0" - chokidar "^1.0.0" + async "^2.1.2" + chokidar "^1.4.3" graceful-fs "^4.1.2" wbuf@^1.1.0, wbuf@^1.4.0: @@ -6859,19 +7020,13 @@ webidl-conversions@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.1.tgz#8015a17ab83e7e1b311638486ace81da6ce206a0" -webpack-core@~0.6.9: +webpack-core@^0.6.8: version "0.6.9" resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" dependencies: source-list-map "~0.1.7" source-map "~0.4.1" -webpack-custom-stats-patch@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/webpack-custom-stats-patch/-/webpack-custom-stats-patch-0.3.0.tgz#544491a63b8e0ad9a61f93da5f8fc2d22a69d8b7" - dependencies: - lodash.merge "^4.4.0" - webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.10.2.tgz#2e252ce1dfb020dbda1ccb37df26f30ab014dbd1" @@ -6930,25 +7085,44 @@ webpack-sources@^0.1.0: source-list-map "~0.1.7" source-map "~0.5.3" -webpack@^1.14.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.15.0.tgz#4ff31f53db03339e55164a9d468ee0324968fe98" +webpack-sources@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.2.3.tgz#17c62bfaf13c707f9d02c479e0dcdde8380697fb" dependencies: - acorn "^3.0.0" - async "^1.3.0" - clone "^1.0.2" - enhanced-resolve "~0.9.0" - interpret "^0.6.4" - loader-utils "^0.2.11" - memory-fs "~0.3.0" + source-list-map "^1.1.1" + source-map "~0.5.3" + +webpack-subresource-integrity@^1.0.0-rc.1: + version "1.0.0-rc.1" + resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-1.0.0-rc.1.tgz#2e92b3917cdb34de58e2b313ff2f9d4bfa081c78" + dependencies: + webpack-core "^0.6.8" + +webpack@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.5.1.tgz#61742f0cf8af555b87460a9cd8bba2f1e3ee2fce" + dependencies: + acorn "^5.0.0" + acorn-dynamic-import "^2.0.0" + ajv "^4.7.0" + ajv-keywords "^1.1.1" + async "^2.1.2" + enhanced-resolve "^3.0.0" + interpret "^1.0.0" + json-loader "^0.5.4" + json5 "^0.5.1" + loader-runner "^2.3.0" + loader-utils "^0.2.16" + memory-fs "~0.4.1" mkdirp "~0.5.0" - node-libs-browser "^0.7.0" - optimist "~0.6.0" + node-libs-browser "^2.0.0" + source-map "^0.5.3" supports-color "^3.1.0" - tapable "~0.1.8" - uglify-js "~2.7.3" - watchpack "^0.2.1" - webpack-core "~0.6.9" + tapable "~0.2.5" + uglify-js "^2.8.5" + watchpack "^1.3.1" + webpack-sources "^0.2.3" + yargs "^6.0.0" websocket-driver@>=0.5.1: version "0.6.5"