treeherder/webpack.config.js

312 строки
6.8 KiB
JavaScript

const path = require('path');
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HotModuleReplacementPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { ProvidePlugin } = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const commonConfig = {
target: 'web',
context: path.resolve(__dirname),
stats: {
children: false,
entrypoints: false,
modules: false,
},
output: {
path: path.resolve(__dirname, '.build'),
publicPath: '/',
},
resolve: {
alias: {
'react-native': 'react-native-web',
},
extensions: [
'.web.jsx',
'.web.js',
'.wasm',
'.mjs',
'.jsx',
'.js',
'.json',
],
fallback: {
url: require.resolve('url'),
crypto: require.resolve('crypto-browserify'),
stream: require.resolve('stream-browserify'),
buffer: require.resolve('buffer'),
assert: require.resolve('assert'),
fs: false,
tls: false,
},
},
module: {
rules: [
{
test: /\.(mjs|jsx|js)$/,
resolve: {
fullySpecified: false, // disable the behaviour
},
},
{
test: /\.html$/,
use: {
loader: 'html-loader',
options: {
sources: {
list: [
{
tag: 'img',
attribute: 'img-src',
type: 'src',
},
{
tag: 'a',
attribute: 'href',
type: 'src',
},
],
},
},
},
},
{
test: /\.(mjs|jsx|js)$/,
type: 'javascript/auto',
include: [
path.resolve(__dirname, 'ui'),
path.resolve(__dirname, 'tests/ui'),
],
use: [
{
loader: 'babel-loader',
},
],
},
],
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
}),
new webpack.ProvidePlugin({
process: 'process/browser',
}),
new CopyWebpackPlugin({
patterns: ['ui/contribute.json', 'ui/revision.txt', 'ui/robots.txt'],
}),
new ProvidePlugin({
jQuery: 'jquery',
'window.jQuery': 'jquery',
}),
],
entry: {
index: ['./ui/index'],
},
};
const developmentConfig = {
mode: 'development',
devtool: 'eval-cheap-module-source-map',
devServer: {
host: '0.0.0.0',
port: 5000,
hot: true,
historyApiFallback: true,
open: true,
proxy: {
'/api': {
changeOrigin: true,
headers: {
referer: 'https://treeherder.mozilla.org/webpack-dev-server',
},
// Support BACKEND environment variable provided by npm run scripts
target: process.env.BACKEND || 'https://treeherder.mozilla.org',
onProxyRes: (proxyRes) => {
// Strip the cookie `secure` attribute, otherwise production's cookies
// will be rejected by the browser when using non-HTTPS localhost:
// https://github.com/nodejitsu/node-http-proxy/pull/1166
const removeSecure = (str) => str.replace(/; secure/i, '');
const cookieHeader = proxyRes.headers['set-cookie'];
if (cookieHeader) {
proxyRes.headers['set-cookie'] = Array.isArray(cookieHeader)
? cookieHeader.map(removeSecure)
: removeSecure(cookieHeader);
}
},
},
},
devMiddleware: {
stats: {
all: false,
errors: true,
timings: true,
warnings: true,
},
},
static: {
watch: {
usePolling: true,
interval: 1000,
ignored: /node_modules/,
},
},
},
output: {
filename: 'assets/[name].js',
},
optimization: {
minimize: false,
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
name: false,
},
runtimeChunk: 'single',
},
plugins: [
new HotModuleReplacementPlugin({
template: 'ui/index.html',
lang: 'en',
filename: 'index.html',
}),
],
infrastructureLogging: {
level: 'warn',
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
importLoaders: 0,
},
},
],
},
{
test: /\.(eot|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset/resource',
generator: {
filename: 'assets/[name].[ext]',
},
},
{
test: /\.(ico|png|jpg|jpeg|gif|svg|webp)(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset',
generator: {
filename: 'assets/[name].[ext]',
},
},
],
},
};
const productionConfig = {
mode: 'production',
devtool: 'source-map',
output: {
filename: 'assets/[name].[contenthash:8].js',
},
optimization: {
minimize: true,
splitChunks: {
chunks: 'all',
maxInitialRequests: 5,
name: false,
cacheGroups: {
redoc: {
test: /[\\/]node_modules[\\/](mobx|redoc|styled-components)[\\/]/,
name: 'redoc',
chunks: 'all',
},
},
},
runtimeChunk: 'single',
},
performance: {
hints: 'error',
maxAssetSize: 2300000,
maxEntrypointSize: 3000000,
},
plugins: [
new HtmlWebpackPlugin({
template: 'ui/index.html',
appMountId: 'root',
lang: 'en',
meta: false,
filename: 'index.html',
chunks: ['index', 'redoc'],
}),
new MiniCssExtractPlugin({
filename: 'assets/[name].[contenthash:8].css',
}),
new CleanWebpackPlugin({
verbose: false,
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 0,
},
},
],
},
{
test: /\.(eot|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset/resource',
generator: {
filename: 'assets/[name].[hash:8].[ext]',
},
},
{
test: /\.(ico|png|jpg|jpeg|gif|svg|webp)(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset',
generator: {
filename: 'assets/[name].[hash:8].[ext]',
},
},
],
},
};
module.exports = (env, args) => {
switch (args.mode) {
case 'development':
return merge(commonConfig, developmentConfig);
case 'production':
return merge(commonConfig, productionConfig);
default:
throw new Error('No matching configuration was found!');
}
};