summaryrefslogtreecommitdiff
path: root/config/webpack
diff options
context:
space:
mode:
Diffstat (limited to 'config/webpack')
-rw-r--r--config/webpack/custom/rules.js90
-rw-r--r--config/webpack/development.js5
-rw-r--r--config/webpack/environment.js43
-rw-r--r--config/webpack/gitlab.js68
-rw-r--r--config/webpack/production.js24
-rw-r--r--config/webpack/test.js5
6 files changed, 235 insertions, 0 deletions
diff --git a/config/webpack/custom/rules.js b/config/webpack/custom/rules.js
new file mode 100644
index 00000000000..2e9780abfb6
--- /dev/null
+++ b/config/webpack/custom/rules.js
@@ -0,0 +1,90 @@
+const path = require('path');
+const ROOT_PATH = path.resolve(__dirname, '../../../');
+const CACHE_PATH = process.env.WEBPACK_CACHE_PATH || path.join(ROOT_PATH, 'tmp/cache');
+const VUE_VERSION = require('vue/package.json').version;
+const VUE_LOADER_VERSION = require('vue-loader/package.json').version;
+const IS_DEV_SERVER = process.env.NODE_ENV === 'development';
+
+module.exports = [
+ {
+ type: 'javascript/auto',
+ test: /\.mjs$/,
+ use: [],
+ },
+ {
+ test: /\.js$/,
+ exclude: path => /node_modules|vendor[\\/]assets/.test(path) && !/\.vue\.js/.test(path),
+ loader: 'babel-loader',
+ options: {
+ cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
+ },
+ },
+ {
+ test: /\.vue$/,
+ loader: 'vue-loader',
+ options: {
+ cacheDirectory: path.join(CACHE_PATH, 'vue-loader'),
+ cacheIdentifier: [
+ process.env.NODE_ENV || 'development',
+ process.version,
+ VUE_VERSION,
+ VUE_LOADER_VERSION,
+ ].join('|'),
+ },
+ },
+ {
+ test: /\.(graphql|gql)$/,
+ exclude: /node_modules/,
+ loader: 'graphql-tag/loader',
+ },
+ {
+ test: /\.svg$/,
+ loader: 'raw-loader',
+ },
+ {
+ test: /\.(gif|png)$/,
+ loader: 'url-loader',
+ options: {limit: 2048},
+ },
+ {
+ test: /\_worker\.js$/,
+ use: [
+ {
+ loader: 'worker-loader',
+ options: {
+ name: '[name].[hash:8].worker.js',
+ inline: IS_DEV_SERVER,
+ },
+ },
+ 'babel-loader',
+ ],
+ },
+ {
+ test: /\.(worker(\.min)?\.js|pdf|bmpr)$/,
+ exclude: /node_modules/,
+ loader: 'file-loader',
+ options: {
+ name: '[name].[hash:8].[ext]',
+ },
+ },
+ {
+ test: /.css$/,
+ use: [
+ 'vue-style-loader',
+ {
+ loader: 'css-loader',
+ options: {
+ name: '[name].[hash:8].[ext]',
+ },
+ },
+ ],
+ },
+ {
+ test: /\.(eot|ttf|woff|woff2)$/,
+ include: /node_modules\/katex\/dist\/fonts/,
+ loader: 'file-loader',
+ options: {
+ name: '[name].[hash:8].[ext]',
+ },
+ },
+];
diff --git a/config/webpack/development.js b/config/webpack/development.js
new file mode 100644
index 00000000000..89d35d93896
--- /dev/null
+++ b/config/webpack/development.js
@@ -0,0 +1,5 @@
+process.env.NODE_ENV = process.env.NODE_ENV || 'development';
+
+const environment = require('./environment');
+
+module.exports = environment.toWebpackConfig();
diff --git a/config/webpack/environment.js b/config/webpack/environment.js
new file mode 100644
index 00000000000..a79bb43a1ff
--- /dev/null
+++ b/config/webpack/environment.js
@@ -0,0 +1,43 @@
+const { environment } = require('@rails/webpacker');
+const webpack = require('webpack');
+
+// custom webpack Plugins
+const { VueLoaderPlugin } = require('vue-loader');
+const { StatsWriterPlugin } = require('webpack-stats-plugin');
+const MonacoEditorPlugin = require('monaco-editor-webpack-plugin');
+
+const customRules = require('./custom/rules');
+
+// plugin initialization
+environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin());
+environment.loaders = customRules; // webpacker use 'loaders' as key for 'rules'
+
+environment.plugins.append('StatsWriterPlugin', new StatsWriterPlugin({
+ // manifest filename must match config.webpack.manifest_filename
+ // webpack-rails only needs assetsByChunkName to function properly
+ filename: 'manifest.json',
+ transform: function (data, opts) {
+ const stats = opts.compiler.getStats().toJson({
+ chunkModules: false,
+ source: false,
+ chunks: false,
+ modules: false,
+ assets: true,
+ });
+ return JSON.stringify(stats, null, 2);
+ },
+ })
+);
+
+environment.plugins.append('MonacoEditorPlugin', new MonacoEditorPlugin());
+
+environment.plugins.append('IgnorePlugin',
+ // prevent pikaday from including moment.js
+ new webpack.IgnorePlugin(/moment/, /pikaday/)
+);
+
+// custom GitLab config
+const gitlabConfig = require('./gitlab');
+environment.config.merge(gitlabConfig);
+
+module.exports = environment;
diff --git a/config/webpack/gitlab.js b/config/webpack/gitlab.js
new file mode 100644
index 00000000000..c23f3da9211
--- /dev/null
+++ b/config/webpack/gitlab.js
@@ -0,0 +1,68 @@
+const path = require('path');
+
+const ROOT_PATH = path.resolve(__dirname, '../..');
+const IS_EE = require('./../helpers/is_ee_env');
+
+const alias = {
+ '~': path.join(ROOT_PATH, 'app/assets/javascripts'),
+ emojis: path.join(ROOT_PATH, 'fixtures/emojis'),
+ empty_states: path.join(ROOT_PATH, 'app/views/shared/empty_states'),
+ icons: path.join(ROOT_PATH, 'app/views/shared/icons'),
+ images: path.join(ROOT_PATH, 'app/assets/images'),
+ vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
+ vue$: 'vue/dist/vue.esm.js',
+ spec: path.join(ROOT_PATH, 'spec/javascripts'),
+
+ // the following resolves files which are different between CE and EE
+ ee_else_ce: path.join(ROOT_PATH, 'app/assets/javascripts'),
+};
+
+if (IS_EE) {
+ Object.assign(alias, {
+ ee: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
+ ee_empty_states: path.join(ROOT_PATH, 'ee/app/views/shared/empty_states'),
+ ee_icons: path.join(ROOT_PATH, 'ee/app/views/shared/icons'),
+ ee_images: path.join(ROOT_PATH, 'ee/app/assets/images'),
+ ee_spec: path.join(ROOT_PATH, 'ee/spec/javascripts'),
+ ee_else_ce: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
+ });
+}
+
+module.exports = {
+ // resolve
+ resolve: {
+ alias,
+ },
+
+ // module
+ module: {
+ strictExportPresence: true,
+ },
+
+ // optimization
+ // optimization: {
+ // runtimeChunk: 'single',
+ // splitChunks: {
+ // maxInitialRequests: 4,
+ // cacheGroups: {
+ // default: false,
+ // common: () => ({
+ // priority: 20,
+ // name: 'main',
+ // chunks: 'initial',
+ // minChunks: autoEntriesCount * 0.9,
+ // }),
+ // vendors: {
+ // priority: 10,
+ // chunks: 'async',
+ // test: /[\\/](node_modules|vendor[\\/]assets[\\/]javascripts)[\\/]/,
+ // },
+ // commons: {
+ // chunks: 'all',
+ // minChunks: 2,
+ // reuseExistingChunk: true,
+ // },
+ // },
+ // },
+ // },
+};
diff --git a/config/webpack/production.js b/config/webpack/production.js
new file mode 100644
index 00000000000..4ac9da35ad0
--- /dev/null
+++ b/config/webpack/production.js
@@ -0,0 +1,24 @@
+process.env.NODE_ENV = process.env.NODE_ENV || 'production';
+
+const environment = require('./environment');
+
+const path = require('path');
+const ROOT_PATH = path.resolve(__dirname, '../..');
+
+// custom webpack plugins - production only
+const CompressionPlugin = require('compression-webpack-plugin');
+const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
+
+// plugin initialization
+environment.plugins.append('CompressionPlugin', new CompressionPlugin());
+environment.plugins.append('BundleAnalyzerPlugin', new BundleAnalyzerPlugin({
+ analyzerMode: 'static',
+ generateStatsFile: true,
+ openAnalyzer: false,
+ reportFilename: path.join(ROOT_PATH, 'webpack-report/index.html'),
+ statsFilename: path.join(ROOT_PATH, 'webpack-report/stats.json'),
+ })
+);
+
+// export final webpack configuration
+module.exports = environment.toWebpackConfig();
diff --git a/config/webpack/test.js b/config/webpack/test.js
new file mode 100644
index 00000000000..c5edff94ad2
--- /dev/null
+++ b/config/webpack/test.js
@@ -0,0 +1,5 @@
+process.env.NODE_ENV = process.env.NODE_ENV || 'development'
+
+const environment = require('./environment')
+
+module.exports = environment.toWebpackConfig()