Skip to content

Instantly share code, notes, and snippets.

@evanpurkhiser
Created December 27, 2018 15:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save evanpurkhiser/e0ef9b4602aa0941e1deb3bb2fe77eea to your computer and use it in GitHub Desktop.
Save evanpurkhiser/e0ef9b4602aa0941e1deb3bb2fe77eea to your computer and use it in GitHub Desktop.
const localeCatalog = JSON.parse(fs.readFileSync(localeCatalogPath, 'utf8'));
// moment uses a lowercase IETF language tag, while django uses the underscore
// with uppercase syntax
const normalizeLocale = locale => locale.toLowerCase().replace('_', '-');
const supportedLocales = localeCatalog.supported_locales;
const normalizedSuppotedLocales = supportedLocales.map(normalizeLocale);
// A mapping of chunk groups used for locale code splitting
const localeChunkGroups = {};
// No need to split the english locale out as it will be completely empty and
// is not included by the django layout.html
const chunkedLocales = supportedLocales.filter(l => l !== 'en');
for (const locale of chunkedLocales) {
const normalizedLocale = normalizeLocale(locale);
const group = `locale/${locale}`;
// Modify this list of tests to include other modules that should be chunked
// with each locale.
const localeGroupTests = [
new RegExp(`locale\\/${locale}\\/.*\\.po$`),
new RegExp(`moment\\/locale\\/${normalizedLocale}\\.js$`),
];
// module test taken from [0] and modified to support testing against
// multiple expressions.
//
// [0] https://github.com/webpack/webpack/blob/7a6a71f1e9349f86833de12a673805621f0fc6f6/lib/optimize/SplitChunksPlugin.js#L309-L320
const groupTest = module =>
localeGroupTests.some(
pattern =>
module.nameForCondition && pattern.test(module.nameForCondition())
? true
: Array.from(module.chunksIterable).some(c => c.name && pattern.test(c.name))
);
localeChunkGroups[group] = {
name: group,
test: groupTest,
enforce: true,
};
}
// Restirct translation files that are pulled in through app/translations.jsx
// and through moment/locale/* to only those which we create bundles for via
// locale/catalogs.json.
const localeRestrictionPlugins = [
new webpack.ContextReplacementPlugin(
/sentry-locale$/,
path.join(__dirname, 'src', 'sentry', 'locale', path.sep),
true,
new RegExp(`(${supportedLocales.join('|')})/.*\\.po$`)
),
new webpack.ContextReplacementPlugin(
/moment\/locale/,
new RegExp(`(${normalizedSuppotedLocales.join('|')})\\.js$`)
),
];
/**
* Explicit codesplitting cache groups
*/
const cacheGroups = {
vendors: {
enforce: true,
name: 'vendor',
test: /[\\/]node_modules[\\/]/,
priority: -10,
},
...localeChunkGroups,
};
/**
* Main Webpack config for Sentry React SPA.
*/
const appConfig = {
mode: WEBPACK_MODE,
entry: {app: 'app'},
context: path.join(__dirname, staticPrefix),
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: path.join(__dirname, staticPrefix),
exclude: /(vendor|node_modules|dist)/,
query: babelConfig,
},
{
test: /\.po$/,
loader: 'po-catalog-loader',
query: {
referenceExtensions: ['.js', '.jsx'],
domain: 'sentry',
},
},
{
test: /app\/icons\/.*\.svg$/,
use: [{loader: 'svg-sprite-loader'}, {loader: 'svgo-loader'}],
},
{
test: /\.css/,
use: [{loader: 'style-loader'}, {loader: 'css-loader'}],
},
{
test: /\.(woff|woff2|ttf|eot|svg|png|gif|ico|jpg)($|\?)/,
exclude: /app\/icons\/.*\.svg$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
],
},
],
noParse: [
// don't parse known, pre-built javascript files (improves webpack perf)
/dist\/jquery\.js/,
/jed\/jed\.js/,
/marked\/lib\/marked\.js/,
],
},
plugins: [
new LodashModuleReplacementPlugin({
collections: true,
currying: true, // these are enabled to support lodash/fp/ features
flattening: true, // used by a dependency of react-mentions
shorthands: true,
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'root.jQuery': 'jquery',
}),
new ExtractTextPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
IS_PERCY: JSON.stringify(
process.env.CI && !!process.env.PERCY_TOKEN && !!process.env.TRAVIS
),
},
}),
...localeRestrictionPlugins,
new BundleAnalyzerPlugin(),
],
resolve: {
alias: {
app: path.join(__dirname, 'src', 'sentry', 'static', 'sentry', 'app'),
'app-test': path.join(__dirname, 'tests', 'js'),
'app-test-helpers': path.join(__dirname, 'tests', 'js', 'helpers'),
'sentry-locale': path.join(__dirname, 'src', 'sentry', 'locale'),
'integration-docs-platforms': IS_TEST
? path.join(__dirname, 'tests/fixtures/integration-docs/_platforms.json')
: path.join(__dirname, 'src/sentry/integration-docs/_platforms.json'),
},
modules: [path.join(__dirname, staticPrefix), 'node_modules'],
extensions: ['.jsx', '.js', '.json'],
},
output: {
path: distPath,
filename: '[name].js',
libraryTarget: 'var',
library: 'exports',
sourceMapFilename: '[name].js.map',
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups,
},
},
devtool: IS_PRODUCTION ? 'source-map' : false,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment