353 lines
17 KiB
JavaScript
353 lines
17 KiB
JavaScript
const path = require('path');
|
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
|
|
const fs = require('fs');
|
|
const webpack = require('webpack');
|
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
|
|
const TerserPlugin = require('terser-webpack-plugin');
|
|
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
|
const safePostCssParser = require('postcss-safe-parser');
|
|
const { WebpackManifestPlugin: ManifestPlugin } = require('webpack-manifest-plugin');
|
|
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
|
|
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
|
|
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
|
|
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
|
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
|
|
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
|
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
|
|
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
|
|
|
|
const postcssNormalize = require('postcss-normalize');
|
|
const resolvePath = (relative) => path.resolve(fs.realpathSync(process.cwd()), relative);
|
|
|
|
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
|
|
|
|
const emitErrorsAsWarnings = process.env.ESLINT_NO_DEV_ERRORS === 'true';
|
|
const disableESLintPlugin = process.env.DISABLE_ESLINT_PLUGIN === 'true';
|
|
|
|
const imageInlineSizeLimit = parseInt(process.env.IMAGE_INLINE_SIZE_LIMIT || '10000');
|
|
|
|
// Check if TypeScript is setup
|
|
const useTypeScript = fs.existsSync(resolvePath('tsconfig.json'));
|
|
|
|
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
|
|
const cssRegex = /\.css$/;
|
|
const cssModuleRegex = /\.module\.css$/;
|
|
const sassRegex = /\.(scss|sass)$/;
|
|
const sassModuleRegex = /\.module\.(scss|sass)$/;
|
|
const swSrc = 'not-existing-file.txt';
|
|
|
|
module.exports = (webpackEnv) => {
|
|
// const isEnvDevelopment = webpackEnv === 'development';
|
|
const isEnvDevelopment = false;
|
|
// const isEnvProduction = webpackEnv === 'production';
|
|
const isEnvProduction = !isEnvDevelopment;
|
|
|
|
const getStyleLoaders = (cssOptions, preProcessor) => {
|
|
const loaders = [
|
|
isEnvDevelopment && require.resolve('style-loader'),
|
|
isEnvProduction && {
|
|
loader: MiniCssExtractPlugin.loader,
|
|
// css is located in `static/css`, use '../../' to locate index.html folder
|
|
// in production `paths.publicUrlOrPath` can be a relative path
|
|
options: { publicPath: '../../' },
|
|
},
|
|
{
|
|
loader: require.resolve('css-loader'),
|
|
options: cssOptions,
|
|
},
|
|
{
|
|
// Options for PostCSS as we reference these options twice
|
|
// Adds vendor prefixing based on your specified browser support in
|
|
// package.json
|
|
loader: require.resolve('postcss-loader'),
|
|
options: {
|
|
// Necessary for external CSS imports to work
|
|
// https://github.com/facebook/create-react-app/issues/2677
|
|
postcssOptions: {
|
|
ident: 'postcss',
|
|
plugins: () => [
|
|
require('postcss-flexbugs-fixes'),
|
|
require('postcss-preset-env')({
|
|
autoprefixer: {
|
|
flexbox: 'no-2009',
|
|
},
|
|
stage: 3,
|
|
}),
|
|
// Adds PostCSS Normalize as the reset css with default options,
|
|
// so that it honors browserslist config in package.json
|
|
// which in turn let's users customize the target behavior as per their needs.
|
|
postcssNormalize(),
|
|
],
|
|
},
|
|
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
|
|
},
|
|
},
|
|
].filter(Boolean);
|
|
if (preProcessor) {
|
|
loaders.push(
|
|
{
|
|
loader: require.resolve('resolve-url-loader'),
|
|
options: {
|
|
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
|
|
root: resolvePath('src/client'),
|
|
},
|
|
},
|
|
{
|
|
loader: require.resolve(preProcessor),
|
|
options: {
|
|
sourceMap: true,
|
|
},
|
|
}
|
|
);
|
|
}
|
|
return loaders;
|
|
};
|
|
|
|
return {
|
|
mode: 'development',
|
|
entry: './src/client/ts/index.tsx',
|
|
output: {
|
|
path: resolvePath('www'),
|
|
pathinfo: isEnvDevelopment,
|
|
filename: 'index.bundle.js',
|
|
// futureEmitAssets: true,
|
|
// publicPath: '.',
|
|
// // Point sourcemap entries to original disk location (format as URL on Windows)
|
|
// devtoolModuleFilenameTemplate: isEnvProduction
|
|
// ? (info) => path.relative(paths.appSrc, info.absoluteResourcePath).replace(/\\/g, '/')
|
|
// : isEnvDevelopment && ((info) => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
|
|
// globalObject: 'this',
|
|
},
|
|
devtool: 'inline-source-map',
|
|
resolve: {
|
|
extensions: ['.tsx', '.ts', '.js', '.jsx'],
|
|
},
|
|
module: {
|
|
strictExportPresence: true,
|
|
rules: [
|
|
{
|
|
// Disable require.ensure as it's not a standard language feature.
|
|
parser: {
|
|
requireEnsure: false,
|
|
},
|
|
},
|
|
{
|
|
// "oneOf" will traverse all following loaders until one will
|
|
// match the requirements. When no loader matches it will fall
|
|
// back to the "file" loader at the end of the loader list.
|
|
oneOf: [
|
|
{
|
|
test: /\.(ts|tsx)$/,
|
|
exclude: /node_modules/,
|
|
use: {
|
|
loader: 'ts-loader',
|
|
},
|
|
},
|
|
{
|
|
test: /\.(js|jsx)$/,
|
|
exclude: /node_modules/,
|
|
use: {
|
|
loader: 'babel-loader',
|
|
},
|
|
},
|
|
|
|
// "postcss" loader applies autoprefixer to our CSS.
|
|
// "css" loader resolves paths in CSS and adds assets as dependencies.
|
|
// "style" loader turns CSS into JS modules that inject <style> tags.
|
|
// In production, we use MiniCSSExtractPlugin to extract that CSS
|
|
// to a file, but in development "style" loader enables hot editing
|
|
// of CSS.
|
|
// By default we support CSS Modules with the extension .module.css
|
|
{
|
|
test: cssRegex,
|
|
exclude: cssModuleRegex,
|
|
use: getStyleLoaders({
|
|
importLoaders: 1,
|
|
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
|
|
}),
|
|
// Don't consider CSS imports dead code even if the
|
|
// containing package claims to have no side effects.
|
|
// Remove this when webpack adds a warning or an error for this.
|
|
// See https://github.com/webpack/webpack/issues/6571
|
|
sideEffects: true,
|
|
},
|
|
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
|
|
// using the extension .module.css
|
|
{
|
|
test: cssModuleRegex,
|
|
use: getStyleLoaders({
|
|
importLoaders: 1,
|
|
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
|
|
modules: {
|
|
getLocalIdent: getCSSModuleLocalIdent,
|
|
},
|
|
}),
|
|
},
|
|
// Opt-in support for SASS (using .scss or .sass extensions).
|
|
// By default we support SASS Modules with the
|
|
// extensions .module.scss or .module.sass
|
|
{
|
|
test: sassRegex,
|
|
exclude: sassModuleRegex,
|
|
use: getStyleLoaders(
|
|
{
|
|
importLoaders: 3,
|
|
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
|
|
},
|
|
'sass-loader'
|
|
),
|
|
// Don't consider CSS imports dead code even if the
|
|
// containing package claims to have no side effects.
|
|
// Remove this when webpack adds a warning or an error for this.
|
|
// See https://github.com/webpack/webpack/issues/6571
|
|
sideEffects: true,
|
|
},
|
|
// Adds support for CSS Modules, but using SASS
|
|
// using the extension .module.scss or .module.sass
|
|
{
|
|
test: sassModuleRegex,
|
|
use: getStyleLoaders(
|
|
{
|
|
importLoaders: 3,
|
|
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
|
|
modules: {
|
|
getLocalIdent: getCSSModuleLocalIdent,
|
|
},
|
|
},
|
|
'sass-loader'
|
|
),
|
|
},
|
|
|
|
// "file" loader makes sure those assets get served by WebpackDevServer.
|
|
// When you `import` an asset, you get its (virtual) filename.
|
|
// In production, they would get copied to the `build` folder.
|
|
// This loader doesn't use a "test" so it will catch all modules
|
|
// that fall through the other loaders.
|
|
{
|
|
loader: require.resolve('file-loader'),
|
|
// Exclude `js` files to keep "css" loader working as it injects
|
|
// its runtime that would otherwise be processed through "file" loader.
|
|
// Also exclude `html` and `json` extensions so they get processed
|
|
// by webpacks internal loaders.
|
|
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
|
|
options: {
|
|
name: 'static/media/[name].[hash:8].[ext]',
|
|
},
|
|
},
|
|
// ** STOP ** Are you adding a new loader?
|
|
// Make sure to add the new loader(s) before the "file" loader.
|
|
],
|
|
},
|
|
],
|
|
},
|
|
plugins: [
|
|
// Generates an `index.html` file with the <script> injected.
|
|
new HtmlWebpackPlugin(
|
|
Object.assign(
|
|
{},
|
|
{
|
|
inject: true,
|
|
template: resolvePath('src/client/index.html'),
|
|
},
|
|
isEnvProduction
|
|
? {
|
|
minify: {
|
|
removeComments: true,
|
|
collapseWhitespace: true,
|
|
removeRedundantAttributes: true,
|
|
useShortDoctype: true,
|
|
removeEmptyAttributes: true,
|
|
removeStyleLinkTypeAttributes: true,
|
|
keepClosingSlash: true,
|
|
minifyJS: true,
|
|
minifyCSS: true,
|
|
minifyURLs: true,
|
|
},
|
|
}
|
|
: undefined
|
|
)
|
|
),
|
|
// Inlines the webpack runtime script. This script is too small to warrant
|
|
// a network request.
|
|
// https://github.com/facebook/create-react-app/issues/5358
|
|
isEnvProduction &&
|
|
shouldInlineRuntimeChunk &&
|
|
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
|
|
//TODO entfernen?
|
|
// Makes some environment variables available in index.html.
|
|
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
|
|
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
|
|
// It will be an empty string unless you specify "homepage"
|
|
// in `package.json`, in which case it will be the pathname of that URL.
|
|
// new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
|
|
|
|
// This gives some necessary context to module not found errors, such as
|
|
// the requesting resource.
|
|
new ModuleNotFoundPlugin(resolvePath('.')),
|
|
|
|
//TODO Check
|
|
// Makes some environment variables available to the JS code, for example:
|
|
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
|
|
// It is absolutely essential that NODE_ENV is set to production
|
|
// during a production build.
|
|
// Otherwise React will be compiled in the very slow development mode.
|
|
// new webpack.DefinePlugin(env.stringified),
|
|
|
|
//TODO Check
|
|
// // Watcher doesn't work well if you mistype casing in a path so we use
|
|
// // a plugin that prints an error when you attempt to do this.
|
|
// // See https://github.com/facebook/create-react-app/issues/240
|
|
// isEnvDevelopment && new CaseSensitivePathsPlugin(),
|
|
|
|
isEnvProduction &&
|
|
new MiniCssExtractPlugin({
|
|
// Options similar to the same options in webpackOptions.output
|
|
// both options are optional
|
|
//TODO evtl in static ordner?
|
|
filename: 'css/[name].[contenthash:8].css',
|
|
chunkFilename: 'css/[name].[contenthash:8].chunk.css',
|
|
}),
|
|
|
|
//TODO publicPath anpassen
|
|
// Generate an asset manifest file with the following content:
|
|
// - "files" key: Mapping of all asset filenames to their corresponding
|
|
// output file so that tools can pick it up without having to parse
|
|
// `index.html`
|
|
// - "entrypoints" key: Array of files which are included in `index.html`,
|
|
// can be used to reconstruct the HTML if necessary
|
|
new ManifestPlugin({
|
|
fileName: 'asset-manifest.json',
|
|
publicPath: '.',
|
|
generate: (seed, files, entrypoints) => {
|
|
const manifestFiles = files.reduce((manifest, file) => {
|
|
manifest[file.name] = file.path;
|
|
return manifest;
|
|
}, seed);
|
|
const entrypointFiles = entrypoints.main.filter((fileName) => !fileName.endsWith('.map'));
|
|
|
|
return {
|
|
files: manifestFiles,
|
|
entrypoints: entrypointFiles,
|
|
};
|
|
},
|
|
}),
|
|
|
|
// Generate a service worker script that will precache, and keep up to date,
|
|
// the HTML & assets that are part of the webpack build.
|
|
isEnvProduction &&
|
|
fs.existsSync(swSrc) &&
|
|
new WorkboxWebpackPlugin.InjectManifest({
|
|
swSrc,
|
|
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
|
|
exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/],
|
|
// Bump up the default maximum size (2mb) that's precached,
|
|
// to make lazy-loading failure scenarios less likely.
|
|
// See https://github.com/cra-template/pwa/issues/13#issuecomment-722667270
|
|
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
|
}),
|
|
].filter(Boolean),
|
|
};
|
|
};
|