diff --git a/.erb/configs/webpack.config.web.prod.ts b/.erb/configs/webpack.config.web.prod.ts new file mode 100644 index 00000000..f0a633a6 --- /dev/null +++ b/.erb/configs/webpack.config.web.prod.ts @@ -0,0 +1,134 @@ +/** + * Build config for electron renderer process + */ + +import path from 'path'; + +import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import MiniCssExtractPlugin from 'mini-css-extract-plugin'; +import TerserPlugin from 'terser-webpack-plugin'; +import webpack from 'webpack'; +import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; +import { merge } from 'webpack-merge'; + +import checkNodeEnv from '../scripts/check-node-env'; +import deleteSourceMaps from '../scripts/delete-source-maps'; +import baseConfig from './webpack.config.base'; +import webpackPaths from './webpack.paths'; + +checkNodeEnv('production'); +deleteSourceMaps(); + +const devtoolsConfig = + process.env.DEBUG_PROD === 'true' + ? { + devtool: 'source-map', + } + : {}; + +const configuration: webpack.Configuration = { + ...devtoolsConfig, + + mode: 'production', + + target: ['web'], + + entry: [path.join(webpackPaths.srcRendererPath, 'index.tsx')], + + output: { + path: webpackPaths.distWebPath, + publicPath: '/', + filename: 'renderer.js', + library: { + type: 'umd', + }, + }, + + module: { + rules: [ + { + test: /\.s?(a|c)ss$/, + use: [ + MiniCssExtractPlugin.loader, + { + loader: 'css-loader', + options: { + modules: { + localIdentName: '[name]__[local]--[hash:base64:5]', + exportLocalsConvention: 'camelCaseOnly', + }, + sourceMap: true, + importLoaders: 1, + }, + }, + 'sass-loader', + ], + include: /\.module\.s?(c|a)ss$/, + }, + { + test: /\.s?(a|c)ss$/, + use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'], + exclude: /\.module\.s?(c|a)ss$/, + }, + // Fonts + { + test: /\.(woff|woff2|eot|ttf|otf)$/i, + type: 'asset/resource', + }, + // Images + { + test: /\.(png|svg|jpg|jpeg|gif)$/i, + type: 'asset/resource', + }, + ], + }, + + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + parallel: true, + }), + new CssMinimizerPlugin(), + ], + }, + + plugins: [ + /** + * Create global constants which can be configured at compile time. + * + * Useful for allowing different behaviour between development builds and + * release builds + * + * NODE_ENV should be production so that modules do not perform certain + * development checks + */ + new webpack.EnvironmentPlugin({ + NODE_ENV: 'production', + DEBUG_PROD: false, + }), + + new MiniCssExtractPlugin({ + filename: 'style.css', + }), + + new BundleAnalyzerPlugin({ + analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled', + }), + + new HtmlWebpackPlugin({ + filename: 'index.html', + template: path.join(webpackPaths.srcRendererPath, 'index.ejs'), + minify: { + collapseWhitespace: true, + removeAttributeQuotes: true, + removeComments: true, + }, + isBrowser: false, + isDevelopment: process.env.NODE_ENV !== 'production', + }), + ], +}; + +export default merge(baseConfig, configuration); diff --git a/.erb/configs/webpack.paths.ts b/.erb/configs/webpack.paths.ts index 08ca36f9..eceb5ea9 100644 --- a/.erb/configs/webpack.paths.ts +++ b/.erb/configs/webpack.paths.ts @@ -19,6 +19,7 @@ const distPath = path.join(appPath, 'dist'); const distMainPath = path.join(distPath, 'main'); const distRemotePath = path.join(distPath, 'remote'); const distRendererPath = path.join(distPath, 'renderer'); +const distWebPath = path.join(distPath, 'web'); const buildPath = path.join(releasePath, 'build'); @@ -38,5 +39,6 @@ export default { distMainPath, distRemotePath, distRendererPath, + distWebPath, buildPath, }; diff --git a/package.json b/package.json index cf88d3cf..2670e679 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,11 @@ "description": "Feishin music server", "version": "0.2.0", "scripts": { - "build": "concurrently \"npm run build:main\" \"npm run build:renderer\" \"npm run build:remote\"", + "build": "concurrently \"npm run build:main\" \"npm run build:renderer\" \"npm run build:remote\" \"npm run build:web\"", "build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts", "build:remote": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.remote.prod.ts", "build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.prod.ts", + "build:web": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.web.prod.ts", "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app", "lint": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx", "lint:fix": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx --fix",