pixelplanet/tools/webpack.config.js
2020-05-11 20:01:42 +02:00

418 lines
12 KiB
JavaScript

/**
*/
import path from 'path';
import webpack from 'webpack';
import AssetsPlugin from 'assets-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import GeneratePackageJsonPlugin from 'generate-package-json-webpack-plugin';
import pkg from '../package.json';
const isDebug = process.argv.includes('--debug');
const isVerbose = process.argv.includes('--verbose');
const isAnalyze = process.argv.includes('--analyze') || process.argv.includes('--analyse');
const basePackageValues = {
name: pkg.name,
version: pkg.version,
private: true,
engines: pkg.engines,
scripts: {
start: 'node --nouse-idle-notification --expose-gc web.js',
},
dependencies: {
mysql2: '^2.1.0',
},
};
const versionsPackageFilename = path.resolve(__dirname, '../package.json');
const config = {
context: path.resolve(__dirname, '..'),
mode: (isDebug) ? 'development' : 'production',
output: {
path: path.resolve(__dirname, '../build/public/assets'),
publicPath: '/assets/',
pathinfo: isVerbose,
},
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
},
module: {
rules: [
{
test: /\.svg$/,
use: [
{
loader: 'babel-loader',
},
{
loader: 'react-svg-loader',
options: {
svgo: {
plugins: [
{
removeViewBox: false,
},
{
removeDimensions: true,
},
],
},
jsx: false, // true outputs JSX tags
},
},
],
},
{
test: /\.html/,
use: [
{
loader: 'html-loader',
options: {
attrs: [':data-src'],
},
},
],
},
{
test: /\.scss/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
// CSS Loader https://github.com/webpack/css-loader
importLoaders: 1,
sourceMap: isDebug,
// CSS Modules https://github.com/css-modules/css-modules
modules: false,
},
},
'sass-loader',
],
},
{
test: /\.md$/,
loader: path.resolve(__dirname, './lib/markdown-loader.js'),
},
{
test: /\.txt$/,
loader: 'raw-loader',
},
{
test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2)(\?.*)?$/,
loader: 'file-loader',
query: {
name: isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]',
},
},
{
test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/,
loader: 'url-loader',
query: {
name: isDebug ? '[path][name].[ext]?[hash:8]' : '[hash:8].[ext]',
limit: 10000,
},
},
],
},
// Don't attempt to continue if there are any errors.
bail: !isDebug,
cache: isDebug,
stats: {
colors: true,
reasons: isDebug,
hash: isVerbose,
version: isVerbose,
timings: true,
chunks: isVerbose,
chunkModules: isVerbose,
cached: isVerbose,
cachedAssets: isVerbose,
},
};
const clientConfig = {
...config,
name: 'client',
target: 'web',
devtool: 'source-map',
entry: {
client: ['./src/client.js'],
globe: ['./src/globe.js'],
},
output: {
...config.output,
filename: isDebug ? '[name].js' : '[name].[chunkhash:8].js',
chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash:8].js',
},
module: {
...config.module,
rules: [
...config.module.rules,
{
test: /\.(js|jsx|ts|tsx)$/,
loader: 'babel-loader',
include: [
path.resolve(__dirname, '../src'),
],
query: {
// https://github.com/babel/babel-loader#options
cacheDirectory: isDebug,
// https://babeljs.io/docs/usage/options/
babelrc: false,
presets: [
// A Babel preset that can automatically determine the Babel plugins and polyfills
// https://github.com/babel/babel-preset-env
['@babel/preset-env', {
targets: {
browsers: pkg.browserslist,
},
modules: false,
useBuiltIns: 'usage',
corejs: {
version: 3,
},
debug: false,
}],
"@babel/typescript",
// JSX, Flow
// https://github.com/babel/babel/tree/master/packages/babel-preset-react
'@babel/react',
],
plugins: [
'@babel/transform-flow-strip-types',
['@babel/plugin-proposal-decorators', { legacy: true }],
'@babel/plugin-proposal-function-sent',
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-numeric-separator',
'@babel/plugin-proposal-throw-expressions',
['@babel/plugin-proposal-class-properties', { loose: true }],
'@babel/proposal-object-rest-spread',
// Adds component stack to warning messages
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
...isDebug ? ['@babel/transform-react-jsx-source'] : [],
// Adds __self attribute to JSX which React will use for some warnings
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
...isDebug ? ['@babel/transform-react-jsx-self'] : [],
// react-optimize
'@babel/transform-react-constant-elements',
'@babel/transform-react-inline-elements',
'transform-react-remove-prop-types',
'transform-react-pure-class-to-function',
],
},
},
{
test: /\.css/,
use: ['style-loader',
{
loader: 'css-loader',
options: {
// CSS Loader https://github.com/webpack/css-loader
sourceMap: isDebug,
// CSS Modules https://github.com/css-modules/css-modules
modules: false,
},
},
],
},
],
},
plugins: [
// Define free variables
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
'process.env.BROWSER': true,
__DEV__: isDebug,
}),
// Emit a file with assets paths
// https://github.com/sporto/assets-webpack-plugin#options
new AssetsPlugin({
path: path.resolve(__dirname, '../build'),
filename: 'assets.json',
prettyPrint: true,
}),
// Webpack Bundle Analyzer
// https://github.com/th0r/webpack-bundle-analyzer
...isAnalyze ? [new BundleAnalyzerPlugin()] : [],
],
optimization: {
splitChunks: {
chunks: 'all',
name: false,
cacheGroups: {
default: false,
vendors: false,
vendor: {
name: 'vendor',
chunks: (chunk) => chunk.name === 'client',
test: /node_modules/,
},
},
},
},
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
// https://webpack.github.io/docs/configuration.html#node
// https://github.com/webpack/node-libs-browser/tree/master/mock
node: {
fs: 'empty',
net: 'empty',
tls: 'empty',
},
};
const webConfig = {
...config,
name: 'web',
target: 'node',
entry: {
web: ['./src/web.js'],
backup: ['./src/backup.js'],
},
output: {
...config.output,
path: path.resolve(__dirname, '../build'),
filename: '[name].js',
libraryTarget: 'commonjs2',
},
module: {
...config.module,
// Override babel-preset-env configuration for Node.js
rules: [
...config.module.rules,
{
test: /\.(js|jsx|ts|tsx)$/,
loader: 'babel-loader',
include: [
path.resolve(__dirname, '../src'),
],
query: {
// https://github.com/babel/babel-loader#options
cacheDirectory: isDebug,
// https://babeljs.io/docs/usage/options/
babelrc: false,
presets: [
// A Babel preset that can automatically determine the Babel plugins and polyfills
// https://github.com/babel/babel-preset-env
['@babel/preset-env', {
targets: {
node: pkg.engines.node.replace(/^\D+/g, ''),
},
modules: false,
useBuiltIns: false,
debug: false,
}],
"@babel/typescript",
// JSX, Flow
// https://github.com/babel/babel/tree/master/packages/babel-preset-react
'@babel/react',
],
plugins: [
'@babel/transform-flow-strip-types',
['@babel/plugin-proposal-decorators', { legacy: true }],
'@babel/plugin-proposal-function-sent',
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-numeric-separator',
'@babel/plugin-proposal-throw-expressions',
['@babel/plugin-proposal-class-properties', { loose: true }],
'@babel/proposal-object-rest-spread',
// Adds component stack to warning messages
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
...isDebug ? ['@babel/transform-react-jsx-source'] : [],
// Adds __self attribute to JSX which React will use for some warnings
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
...isDebug ? ['@babel/transform-react-jsx-self'] : [],
// react-optimize
'@babel/transform-react-constant-elements',
'@babel/transform-react-inline-elements',
'transform-react-remove-prop-types',
'transform-react-pure-class-to-function',
],
},
},
{
test: /\.css/,
use: [
{
loader: 'css-loader',
options: {
// CSS Loader https://github.com/webpack/css-loader
importLoaders: 1,
sourceMap: isDebug,
// CSS Modules https://github.com/css-modules/css-modules
modules: false,
},
},
],
},
],
},
// needed because webpack tries to pack socket.io
externals: [
/\/proxies\.json$/,
/\/canvases\.json$/,
/^\.\/styleassets\.json$/,
/^\.\/assets\.json$/,
(context, request, callback) => {
const isExternal = request.match(/^[@a-z][a-z/.\-0-9]*$/i)
&& !request.match(/\.(css|less|scss|sss)$/i);
callback(null, Boolean(isExternal));
},
],
plugins: [
// Define free variables
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
'process.env.BROWSER': false,
__DEV__: isDebug,
}),
// create package.json for deployment
new GeneratePackageJsonPlugin(basePackageValues, versionsPackageFilename),
],
node: {
console: false,
global: false,
process: false,
Buffer: false,
__filename: false,
__dirname: false,
},
};
export default [clientConfig, webConfig];