about summary refs log tree commit diff
path: root/config/webpack
diff options
context:
space:
mode:
authorNolan Lawson <nolan@nolanlawson.com>2017-05-22 06:06:06 -0700
committerEugen Rochko <eugen@zeonfederated.com>2017-05-22 15:06:06 +0200
commit9d04de1c8d3efb745cfcae3519cee016751b86ec (patch)
tree8242677e98f04c66acf6c0531d0741a238b3c360 /config/webpack
parent73e4468ff31337d1a0afdc70e1717cb5cfae2e82 (diff)
Only load Intl data for current language (#3130)
* Only load Intl data for current language

* Extract common chunk only from application.js and public.js

* Generate locale packs, avoid caching on window object
Diffstat (limited to 'config/webpack')
-rw-r--r--config/webpack/generateLocalePacks.js52
-rw-r--r--config/webpack/shared.js19
2 files changed, 68 insertions, 3 deletions
diff --git a/config/webpack/generateLocalePacks.js b/config/webpack/generateLocalePacks.js
new file mode 100644
index 000000000..10a66e994
--- /dev/null
+++ b/config/webpack/generateLocalePacks.js
@@ -0,0 +1,52 @@
+// To avoid adding a lot of boilerplate, locale packs are
+// automatically generated here. These are written into the tmp/
+// directory and then used to generate locale_en.js, locale_fr.js, etc.
+
+const fs = require('fs');
+const path = require('path');
+const rimraf = require('rimraf');
+const mkdirp = require('mkdirp');
+
+const localesJsonPath = path.join(__dirname, '../../app/javascript/mastodon/locales');
+const locales = fs.readdirSync(localesJsonPath).filter(filename => {
+  return /\.json$/.test(filename) &&
+    !/defaultMessages/.test(filename) &&
+    !/whitelist/.test(filename);
+}).map(filename => filename.replace(/\.json$/, ''));
+
+const outPath = path.join(__dirname, '../../tmp/packs');
+
+rimraf.sync(outPath);
+mkdirp.sync(outPath);
+
+const outPaths = [];
+
+locales.forEach(locale => {
+  const localePath = path.join(outPath, `locale_${locale}.js`);
+  const baseLocale = locale.split('-')[0]; // e.g. 'zh-TW' -> 'zh'
+  const localeDataPath = [
+    // first try react-intl
+    `../../node_modules/react-intl/locale-data/${baseLocale}.js`,
+    // then check locales/locale-data
+    `../../app/javascript/mastodon/locales/locale-data/${baseLocale}.js`,
+    // fall back to English (this is what react-intl does anyway)
+    `../../node_modules/react-intl/locale-data/en.js`,
+  ].filter(filename => fs.existsSync(path.join(outPath, filename)))
+    .map(filename => filename.replace(/..\/..\/node_modules\//, ''))[0];
+
+  const localeContent = `//
+// locale_${locale}.js
+// automatically generated by generateLocalePacks.js
+//
+import messages from '../../app/javascript/mastodon/locales/${locale}.json';
+import localeData from ${JSON.stringify(localeDataPath)};
+import { setLocale } from '../../app/javascript/mastodon/locales';
+setLocale({messages, localeData});
+`;
+  fs.writeFileSync(localePath, localeContent, 'utf8');
+  outPaths.push(localePath);
+});
+
+module.exports = outPaths;
+
+
diff --git a/config/webpack/shared.js b/config/webpack/shared.js
index 4986ea24d..1d75e2af2 100644
--- a/config/webpack/shared.js
+++ b/config/webpack/shared.js
@@ -10,15 +10,20 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin');
 const ManifestPlugin = require('webpack-manifest-plugin');
 const extname = require('path-complete-extname');
 const { env, paths, publicPath, loadersDir } = require('./configuration.js');
+const localePackPaths = require('./generateLocalePacks');
 
 const extensionGlob = `**/*{${paths.extensions.join(',')}}*`;
 const packPaths = sync(join(paths.source, paths.entry, extensionGlob));
+const entryPacks = [].concat(packPaths).concat(localePackPaths);
 
 module.exports = {
-  entry: packPaths.reduce(
+  entry: entryPacks.reduce(
     (map, entry) => {
       const localMap = map;
-      const namespace = relative(join(paths.source, paths.entry), dirname(entry));
+      let namespace = relative(join(paths.source, paths.entry), dirname(entry));
+      if (namespace === '../../../tmp/packs') {
+        namespace = ''; // generated by generateLocalePacks.js
+      }
       localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry);
       return localMap;
     }, {}
@@ -41,7 +46,15 @@ module.exports = {
     new ManifestPlugin({ fileName: paths.manifest, publicPath, writeToFileEmit: true }),
     new webpack.optimize.CommonsChunkPlugin({
       name: 'common',
-      minChunks: 2,
+      minChunks: (module, count) => {
+        if (module.resource && /node_modules\/react-intl/.test(module.resource)) {
+          // skip react-intl because it's useless to put in the common chunk,
+          // e.g. because "shared" modules between zh-TW and zh-CN will never
+          // be loaded together
+          return false;
+        }
+        return count >= 2;
+      },
     }),
   ],