about summary refs log tree commit diff
path: root/config/webpack
diff options
context:
space:
mode:
Diffstat (limited to 'config/webpack')
-rw-r--r--config/webpack/configuration.js2
-rw-r--r--config/webpack/development.js40
-rw-r--r--config/webpack/loaders/assets.js12
-rw-r--r--config/webpack/loaders/babel.js13
-rw-r--r--config/webpack/loaders/babel_external.js21
-rw-r--r--config/webpack/production.js39
-rw-r--r--config/webpack/rules/babel.js22
-rw-r--r--config/webpack/rules/css.js (renamed from config/webpack/loaders/sass.js)9
-rw-r--r--config/webpack/rules/file.js20
-rw-r--r--config/webpack/rules/index.js14
-rw-r--r--config/webpack/rules/mark.js (renamed from config/webpack/loaders/mark.js)0
-rw-r--r--config/webpack/rules/node_modules.js23
-rw-r--r--config/webpack/shared.js17
-rw-r--r--config/webpack/translationRunner.js22
14 files changed, 149 insertions, 105 deletions
diff --git a/config/webpack/configuration.js b/config/webpack/configuration.js
index f81d23dd4..926af9b39 100644
--- a/config/webpack/configuration.js
+++ b/config/webpack/configuration.js
@@ -7,7 +7,6 @@ const { lstatSync, readFileSync } = require('fs');
 const glob = require('glob');
 
 const configPath = resolve('config', 'webpacker.yml');
-const loadersDir = join(__dirname, 'loaders');
 const settings = safeLoad(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env.NODE_ENV];
 const flavourFiles = glob.sync('app/javascript/flavours/*/theme.yml');
 const skinFiles = glob.sync('app/javascript/skins/*/*');
@@ -84,6 +83,5 @@ module.exports = {
     CDN_HOST: env.CDN_HOST,
     NODE_ENV: env.NODE_ENV,
   },
-  loadersDir,
   output,
 };
diff --git a/config/webpack/development.js b/config/webpack/development.js
index d54d919ec..1e50a4f46 100644
--- a/config/webpack/development.js
+++ b/config/webpack/development.js
@@ -1,12 +1,10 @@
 // Note: You must restart bin/webpack-dev-server for changes to take effect
 
 const merge = require('webpack-merge');
-const sharedConfig = require('./shared.js');
-const { settings, output } = require('./configuration.js');
+const sharedConfig = require('./shared');
+const { settings, output } = require('./configuration');
 
-const watchOptions = {
-  ignored: /node_modules/,
-};
+const watchOptions = {};
 
 if (process.env.VAGRANT) {
   // If we are in Vagrant, we can't rely on inotify to update us with changed
@@ -17,7 +15,7 @@ if (process.env.VAGRANT) {
 
 module.exports = merge(sharedConfig, {
   mode: 'development',
-
+  cache: true,
   devtool: 'cheap-module-eval-source-map',
 
   stats: {
@@ -30,15 +28,33 @@ module.exports = merge(sharedConfig, {
 
   devServer: {
     clientLogLevel: 'none',
-    https: settings.dev_server.https,
+    compress: settings.dev_server.compress,
+    quiet: settings.dev_server.quiet,
+    disableHostCheck: settings.dev_server.disable_host_check,
     host: settings.dev_server.host,
     port: settings.dev_server.port,
+    https: settings.dev_server.https,
+    hot: settings.dev_server.hmr,
     contentBase: output.path,
+    inline: settings.dev_server.inline,
+    useLocalIp: settings.dev_server.use_local_ip,
+    public: settings.dev_server.public,
     publicPath: output.publicPath,
-    compress: true,
-    headers: { 'Access-Control-Allow-Origin': '*' },
-    historyApiFallback: true,
-    disableHostCheck: true,
-    watchOptions: watchOptions,
+    historyApiFallback: {
+      disableDotRule: true,
+    },
+    headers: settings.dev_server.headers,
+    overlay: settings.dev_server.overlay,
+    stats: {
+      entrypoints: false,
+      errorDetails: false,
+      modules: false,
+      moduleTrace: false,
+    },
+    watchOptions: Object.assign(
+      {},
+      settings.dev_server.watch_options,
+      watchOptions
+    ),
   },
 });
diff --git a/config/webpack/loaders/assets.js b/config/webpack/loaders/assets.js
deleted file mode 100644
index 643b3eeb0..000000000
--- a/config/webpack/loaders/assets.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const { env, publicPath } = require('../configuration.js');
-
-module.exports = {
-  test: /\.(jpg|jpeg|png|gif|svg|eot|ttf|woff|woff2)$/i,
-  use: [{
-    loader: 'file-loader',
-    options: {
-      publicPath,
-      name: env.NODE_ENV === 'production' ? '[name]-[hash].[ext]' : '[name].[ext]',
-    },
-  }],
-};
diff --git a/config/webpack/loaders/babel.js b/config/webpack/loaders/babel.js
deleted file mode 100644
index d8d785b98..000000000
--- a/config/webpack/loaders/babel.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const { resolve } = require('path');
-
-const env = process.env.NODE_ENV || 'development';
-
-module.exports = {
-  test: /\.js$/,
-  exclude: /node_modules/,
-  loader: 'babel-loader',
-  options: {
-    sourceRoot: 'app/javascript',
-    cacheDirectory: env === 'development' ? false : resolve(__dirname, '..', '..', '..', 'tmp', 'cache', 'babel-loader'),
-  },
-};
diff --git a/config/webpack/loaders/babel_external.js b/config/webpack/loaders/babel_external.js
deleted file mode 100644
index 39e74ed90..000000000
--- a/config/webpack/loaders/babel_external.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const { resolve } = require('path');
-
-const env = process.env.NODE_ENV || 'development';
-
-if (env === 'development') {
-  module.exports = {};
-} else {
-  // babel options to apply only to external libraries, e.g. remove-prop-types
-  module.exports = {
-    test: /\.js$/,
-    include: /node_modules/,
-    loader: 'babel-loader',
-    options: {
-      babelrc: false,
-      plugins: [
-        'transform-react-remove-prop-types',
-      ],
-      cacheDirectory: env === 'development' ? false : resolve(__dirname, '..', '..', '..', 'tmp', 'cache', 'babel-loader-external'),
-    },
-  };
-}
diff --git a/config/webpack/production.js b/config/webpack/production.js
index d37e11792..c829ff6f1 100644
--- a/config/webpack/production.js
+++ b/config/webpack/production.js
@@ -1,15 +1,14 @@
 // Note: You must restart bin/webpack-dev-server for changes to take effect
 
+const path = require('path');
+const { URL } = require('url');
 const merge = require('webpack-merge');
+const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
+const OfflinePlugin = require('offline-plugin');
 const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
 const CompressionPlugin = require('compression-webpack-plugin');
-const zopfli = require('@gfx/zopfli');
-const sharedConfig = require('./shared.js');
-const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
-const OfflinePlugin = require('offline-plugin');
-const { publicPath } = require('./configuration.js');
-const path = require('path');
-const { URL } = require('url');
+const { output } = require('./configuration');
+const sharedConfig = require('./shared');
 
 let attachmentHost;
 
@@ -28,15 +27,9 @@ if (process.env.S3_ENABLED === 'true') {
 
 module.exports = merge(sharedConfig, {
   mode: 'production',
-
-  output: {
-    filename: '[name]-[chunkhash].js',
-    chunkFilename: '[name]-[chunkhash].js',
-  },
-
-  devtool: 'source-map', // separate sourcemap file, suitable for production
+  devtool: 'source-map',
   stats: 'normal',
-
+  bail: true,
   optimization: {
     minimize: true,
     minimizer: [
@@ -60,23 +53,17 @@ module.exports = merge(sharedConfig, {
 
   plugins: [
     new CompressionPlugin({
-      algorithm(input, compressionOptions, callback) {
-        return zopfli.gzip(input, compressionOptions, callback);
-      },
-      test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/,
+      filename: '[path].gz[query]',
+      cache: true,
+      test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/,
     }),
-    new BundleAnalyzerPlugin({ // generates report.html and stats.json
+    new BundleAnalyzerPlugin({ // generates report.html
       analyzerMode: 'static',
-      generateStatsFile: true,
-      statsOptions: {
-        // allows usage with http://chrisbateman.github.io/webpack-visualizer/
-        chunkModules: true,
-      },
       openAnalyzer: false,
       logLevel: 'silent', // do not bother Webpacker, who runs with --json and parses stdout
     }),
     new OfflinePlugin({
-      publicPath: publicPath, // sw.js must be served from the root to avoid scope issues
+      publicPath: output.publicPath, // sw.js must be served from the root to avoid scope issues
       caches: {
         main: [':rest:'],
         additional: [':externals:'],
diff --git a/config/webpack/rules/babel.js b/config/webpack/rules/babel.js
new file mode 100644
index 000000000..4d25748ee
--- /dev/null
+++ b/config/webpack/rules/babel.js
@@ -0,0 +1,22 @@
+const { join, resolve } = require('path');
+const { env, settings } = require('../configuration');
+
+module.exports = {
+  test: /\.(js|jsx|mjs)$/,
+  include: [
+    settings.source_path,
+    ...settings.resolved_paths,
+  ].map(p => resolve(p)),
+  exclude: /node_modules/,
+  use: [
+    {
+      loader: 'babel-loader',
+      options: {
+        sourceRoot: 'app/javascript',
+        cacheDirectory: join(settings.cache_path, 'babel-loader'),
+        cacheCompression: env.NODE_ENV === 'production',
+        compact: env.NODE_ENV === 'production',
+      },
+    },
+  ],
+};
diff --git a/config/webpack/loaders/sass.js b/config/webpack/rules/css.js
index 5a96096bd..9553cb55b 100644
--- a/config/webpack/loaders/sass.js
+++ b/config/webpack/rules/css.js
@@ -4,7 +4,14 @@ module.exports = {
   test: /\.s?css$/i,
   use: [
     MiniCssExtractPlugin.loader,
-    'css-loader',
+    {
+      loader: 'css-loader',
+      options: {
+        sourceMap: true,
+        importLoaders: 2,
+        localIdentName: '[name]__[local]___[hash:base64:5]',
+      },
+    },
     {
       loader: 'postcss-loader',
       options: {
diff --git a/config/webpack/rules/file.js b/config/webpack/rules/file.js
new file mode 100644
index 000000000..f2fb58780
--- /dev/null
+++ b/config/webpack/rules/file.js
@@ -0,0 +1,20 @@
+const { join } = require('path');
+const { settings } = require('../configuration');
+
+module.exports = {
+  test: new RegExp(`(${settings.static_assets_extensions.join('|')})$`, 'i'),
+  use: [
+    {
+      loader: 'file-loader',
+      options: {
+        name(file) {
+          if (file.includes(settings.source_path)) {
+            return 'media/[path][name]-[hash].[ext]';
+          }
+          return 'media/[folder]/[name]-[hash:8].[ext]';
+        },
+        context: join(settings.source_path),
+      },
+    },
+  ],
+};
diff --git a/config/webpack/rules/index.js b/config/webpack/rules/index.js
new file mode 100644
index 000000000..bbf6b0187
--- /dev/null
+++ b/config/webpack/rules/index.js
@@ -0,0 +1,14 @@
+const babel = require('./babel');
+const css = require('./css');
+const file = require('./file');
+const nodeModules = require('./node_modules');
+
+// Webpack loaders are processed in reverse order
+// https://webpack.js.org/concepts/loaders/#loader-features
+// Lastly, process static files using file loader
+module.exports = {
+  file,
+  css,
+  nodeModules,
+  babel,
+};
diff --git a/config/webpack/loaders/mark.js b/config/webpack/rules/mark.js
index e62a526b0..e62a526b0 100644
--- a/config/webpack/loaders/mark.js
+++ b/config/webpack/rules/mark.js
diff --git a/config/webpack/rules/node_modules.js b/config/webpack/rules/node_modules.js
new file mode 100644
index 000000000..7ed05504b
--- /dev/null
+++ b/config/webpack/rules/node_modules.js
@@ -0,0 +1,23 @@
+const { join } = require('path');
+const { settings, env } = require('../configuration');
+
+module.exports = {
+  test: /\.(js|mjs)$/,
+  include: /node_modules/,
+  exclude: /@babel(?:\/|\\{1,2})runtime/,
+  use: [
+    {
+      loader: 'babel-loader',
+      options: {
+        babelrc: false,
+        plugins: [
+          'transform-react-remove-prop-types',
+        ],
+        cacheDirectory: join(settings.cache_path, 'babel-loader-node-modules'),
+        cacheCompression: env.NODE_ENV === 'production',
+        compact: false,
+        sourceMaps: false,
+      },
+    },
+  ],
+};
diff --git a/config/webpack/shared.js b/config/webpack/shared.js
index 938bab9f5..b6e2537b1 100644
--- a/config/webpack/shared.js
+++ b/config/webpack/shared.js
@@ -5,7 +5,8 @@ const { basename, dirname, join, relative, resolve } = require('path');
 const { sync } = require('glob');
 const MiniCssExtractPlugin = require('mini-css-extract-plugin');
 const AssetsManifestPlugin = require('webpack-assets-manifest');
-const { env, settings, core, flavours, output, loadersDir } = require('./configuration.js');
+const { env, settings, core, flavours, output } = require('./configuration.js');
+const rules = require('./rules');
 const localePacks = require('./generateLocalePacks');
 
 function reducePacks (data, into = {}) {
@@ -56,8 +57,9 @@ module.exports = {
   entry: entries,
 
   output: {
-    filename: '[name].js',
-    chunkFilename: '[name].js',
+    filename: 'js/[name]-[chunkhash].js',
+    chunkFilename: 'js/[name]-[chunkhash].chunk.js',
+    hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
     path: output.path,
     publicPath: output.publicPath,
   },
@@ -85,7 +87,7 @@ module.exports = {
   },
 
   module: {
-    rules: sync(join(loadersDir, '*.js')).map(loader => require(loader)),
+    rules: Object.keys(rules).map(key => rules[key]),
   },
 
   plugins: [
@@ -98,11 +100,14 @@ module.exports = {
       }
     ),
     new MiniCssExtractPlugin({
-      filename: env.NODE_ENV === 'production' ? '[name]-[contenthash].css' : '[name].css',
+      filename: 'css/[name]-[contenthash:8].css',
+      chunkFilename: 'css/[name]-[contenthash:8].chunk.css',
     }),
     new AssetsManifestPlugin({
-      publicPath: true,
+      integrity: false,
+      entrypoints: true,
       writeToDisk: true,
+      publicPath: true,
     }),
   ],
 
diff --git a/config/webpack/translationRunner.js b/config/webpack/translationRunner.js
index e6543fbb7..38050baf8 100644
--- a/config/webpack/translationRunner.js
+++ b/config/webpack/translationRunner.js
@@ -48,8 +48,7 @@ Use yarn "manage:translations -- --help" for usage information
   }
 };
 
-const { argv } = require('yargs')
-  .usage(`Usage: yarn manage:translations -- [OPTIONS] [LANGUAGES]
+const usage = `Usage: yarn manage:translations [OPTIONS] [LANGUAGES]
 
 Manage JavaScript translation files in Mastodon. Generates and update translations in translationsDirectory: ${translationsDirectory}
 
@@ -58,16 +57,15 @@ The RFC5646 language tag for the language you want to test or fix. If you want t
 
 Available languages:
 ${availableLanguages.join(', ')}
-`)
-  .help('h', 'show this message')
-  .alias('h', 'help')
-  .options({
-    f: {
-      alias: 'force',
-      default: false,
-      describe: 'force using the provided languages. create files if not exists.',
-      type: 'boolean',
-    },
+`;
+
+const { argv } = require('yargs')
+  .usage(usage)
+  .option('f', {
+    alias: 'force',
+    default: false,
+    describe: 'force using the provided languages. create files if not exists.',
+    type: 'boolean',
   });
 
 // check if message directory exists