diff --git a/package.json b/package.json index fbda4ea..93fff33 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,8 @@ "terser-webpack-plugin": "^5.2.3", "ts-invariant": "^0.9.1", "tslib": "^2.3.1", + "ts-loader": "^9.2.5", + "typescript": "^4.4.3", "url": "^0.11.0", "url-loader": "^4.1.1", "webpack": "^5.52.0", diff --git a/webpack.config.js b/webpack.config.js index b779068..65eb31a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -6,10 +6,9 @@ const conf = common.configuration; const webpack = require('webpack'); const { - merge + merge, } = require('webpack-merge'); - const fs = require('fs'); const path = require('path'); @@ -30,107 +29,107 @@ const PORT = process.env.PORT || conf.PORT; let plugins = common.plugins; if (COMPRESS) { - plugins.push(require('autoprefixer')); + plugins.push(require('autoprefixer')); - /*plugins.push( - new ImageSpritePlugin({ - exclude: /exclude|original|default-|icons|sprite|svg|logo|favicon/, - commentOrigin: false, - compress: COMPRESS, - extensions: ['png'], - indent: '', - log: true, - //outputPath: path.join(__dirname, conf.APPDIR, conf.DIST), - outputFilename: 'img/sprite-[hash].png', - padding: 0, - }), - );*/ + /*plugins.push( + new ImageSpritePlugin({ + exclude: /exclude|original|default-|icons|sprite|svg|logo|favicon/, + commentOrigin: false, + compress: COMPRESS, + extensions: ['png'], + indent: '', + log: true, + //outputPath: path.join(__dirname, conf.APPDIR, conf.DIST), + outputFilename: 'img/sprite-[hash].png', + padding: 0, + }), + );*/ } const indexPath = path.join(__dirname, conf.APPDIR, conf.SRC, 'index.html'); if (fs.existsSync(indexPath)) { - plugins.push( - new HtmlWebpackPlugin({ - publicPath: '', - template: path.join(conf.APPDIR, conf.SRC, 'index.html'), - templateParameters: { - NODE_ENV: NODE_ENV, - GRAPHQL_URL: conf['GRAPHQL_URL'], - STATIC_URL: conf['STATIC_URL'], - REACT_SCRIPTS: NODE_ENV === 'production' ? - '' : '', + plugins.push( + new HtmlWebpackPlugin({ + publicPath: '', + template: path.join(conf.APPDIR, conf.SRC, 'index.html'), + templateParameters: { + NODE_ENV: NODE_ENV, + GRAPHQL_URL: conf['GRAPHQL_URL'], + STATIC_URL: conf['STATIC_URL'], + REACT_SCRIPTS: NODE_ENV === 'production' ? + '' : '', }, - xhtml: true, + xhtml: true, }), - ); + ); } const faviconPath = path.join(__dirname, conf.APPDIR, conf.SRC, 'favicon.png'); if (fs.existsSync(faviconPath)) { - plugins.push( - new FaviconsWebpackPlugin({ - title: 'Webpack App', - logo: faviconPath, - prefix: '/icons/', - emitStats: false, - persistentCache: true, - inject: false, - statsFilename: path.join( - conf.APPDIR, - conf.DIST, - 'icons', - 'iconstats.json', - ), - icons: { - android: true, - appleIcon: true, - appleStartup: true, - coast: true, - favicons: true, - firefox: true, - opengraph: true, - twitter: true, - yandex: true, - windows: true, + plugins.push( + new FaviconsWebpackPlugin({ + title: 'Webpack App', + logo: faviconPath, + prefix: '/icons/', + emitStats: false, + persistentCache: true, + inject: false, + statsFilename: path.join( + conf.APPDIR, + conf.DIST, + 'icons', + 'iconstats.json', + ), + icons: { + android: true, + appleIcon: true, + appleStartup: true, + coast: true, + favicons: true, + firefox: true, + opengraph: true, + twitter: true, + yandex: true, + windows: true, }, }), - ); + ); } // add themes favicons common.themes.forEach((theme) => { const faviconPath = path.join(__dirname, theme, conf.SRC, 'favicon.png'); if (fs.existsSync(faviconPath)) { - plugins.push( - new FaviconsWebpackPlugin({ - title: 'Webpack App', - logo: faviconPath, - prefix: '/' + theme + '-icons/', - emitStats: false, - persistentCache: true, - inject: false, - statsFilename: path.join( - conf.APPDIR, - conf.DIST, - theme + '-icons', - 'iconstats.json', - ), - icons: { - android: true, - appleIcon: true, - appleStartup: true, - coast: true, - favicons: true, - firefox: true, - opengraph: true, - twitter: true, - yandex: true, - windows: true, + plugins.push( + new FaviconsWebpackPlugin({ + title: 'Webpack App', + logo: faviconPath, + prefix: '/' + theme + '-icons/', + emitStats: false, + persistentCache: true, + inject: false, + statsFilename: path.join( + conf.APPDIR, + conf.DIST, + theme + '-icons', + 'iconstats.json', + ), + icons: { + android: true, + appleIcon: true, + appleStartup: true, + coast: true, + favicons: true, + firefox: true, + opengraph: true, + twitter: true, + yandex: true, + windows: true, }, }), - ); + ); } -}); + }); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') .BundleAnalyzerPlugin; @@ -138,14 +137,14 @@ plugins.push( new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false, - }), + }), ); const cfg = merge(common.webpack, { mode: NODE_ENV, cache: { type: 'filesystem', - }, + }, recordsPath: path.join(__dirname, conf.APPDIR, conf.DIST, 'records.json'), optimization: { //removeAvailableModules: false, @@ -153,7 +152,7 @@ const cfg = merge(common.webpack, { splitChunks: { name: 'vendor', minChunks: 2, - }, + }, concatenateModules: true, //ModuleConcatenationPlugin minimizer: [ new TerserPlugin({ @@ -166,7 +165,7 @@ const cfg = merge(common.webpack, { // sections only apply transformations that are ecma 5 safe // https://github.com/facebook/create-react-app/pull/4234 ecma: 8, - }, + }, compress: { ecma: 5, warnings: false, @@ -175,7 +174,7 @@ const cfg = merge(common.webpack, { // Pending further investigation: // https://github.com/mishoo/UglifyJS2/issues/2011 comparisons: false, - }, + }, keep_fnames: true, keep_classnames: true, @@ -184,19 +183,19 @@ const cfg = merge(common.webpack, { keep_fnames: true, keep_classnames: true, reserved: ['$', 'jQuery', 'jquery'], - }, + }, output: { ecma: 5, comments: false, // Turned on because emoji and regex is not minified properly using default // https://github.com/facebook/create-react-app/issues/2488 ascii_only: true, - }, - }, + }, + }, // Use multi-process parallel running to improve the build speed // Default number of concurrent runs: os.cpus().length - 1 parallel: true, - }), + }), new CssMinimizerPlugin({ parallel: true, minimizerOptions: [{ @@ -204,8 +203,8 @@ const cfg = merge(common.webpack, { 'default', { discardComments: { - removeAll: true - }, + removeAll: true, + }, zindex: true, cssDeclarationSorter: true, reduceIdents: false, @@ -215,25 +214,25 @@ const cfg = merge(common.webpack, { discardUnused: true, discardOverridden: true, discardDuplicates: true, - }, + }, ], - }, ], + },], minify: [ CssMinimizerPlugin.cssnanoMinify, //CssMinimizerPlugin.cleanCssMinify, - ] - }), + ], + }), ], - }, + }, output: { publicPath: path.join(conf.APPDIR, conf.DIST), path: path.join(__dirname, conf.APPDIR, conf.DIST), filename: path.join('js', '[name].js'), - }, + }, module: { - rules: [{ + rules: [{ test: /\.tsx?$/, loader: 'ts-loader' }, { test: /\.jsx?$/, //exclude: /node_modules/, use: { @@ -247,48 +246,48 @@ const cfg = merge(common.webpack, { plugins: [ '@babel/plugin-proposal-class-properties', ], - }, + }, ], //Preset used for env setup plugins: [ - ['@babel/transform-react-jsx'] + ['@babel/transform-react-jsx'], ], cacheDirectory: true, cacheCompression: true, - }, - }, - }, + }, + }, + }, { test: /\.s?css$/, use: [{ loader: MiniCssExtractPlugin.loader, - }, + }, { loader: 'css-loader', options: { sourceMap: true, - }, - }, + }, + }, { loader: 'resolve-url-loader', - }, + }, { loader: 'sass-loader', options: { sourceMap: true, - }, - }, ], - }, + }, + },], + }, { test: /fontawesome([^.]+).(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, - type: "asset/resource", - }, + type: 'asset/resource', + }, { test: /\.(ttf|otf|eot|woff(2)?)$/, - type: "asset/resource", - }, + type: 'asset/resource', + }, { test: /\.(png|webp|jpg|jpeg|gif|svg)$/, - type: "javascript/auto", + type: 'javascript/auto', use: [{ loader: 'img-optimize-loader', options: { @@ -303,33 +302,33 @@ const cfg = merge(common.webpack, { // loseless compression for png optipng: { optimizationLevel: 4, - }, + }, // lossy compression for png. This will generate smaller file than optipng. pngquant: { quality: [0.2, 0.8], - }, + }, // Compression for svg. svgo: true, // Compression for gif. gifsicle: { optimizationLevel: 3, - }, + }, // Compression for jpg. mozjpeg: { progressive: true, quality: 60, - }, - }, + }, + }, inline: { limit: 1, - }, - }, - }, ], - }, ], - }, + }, + }, + },], + },], + }, plugins: plugins, -}); + }); console.log(cfg); module.exports = cfg; diff --git a/webpack.config.serve.js b/webpack.config.serve.js index 905ec6d..cdb949a 100644 --- a/webpack.config.serve.js +++ b/webpack.config.serve.js @@ -10,7 +10,7 @@ const fs = require('fs'); //const autoprefixer = require('autoprefixer'); const webpack = require('webpack'); const { - merge + merge, } = require('webpack-merge'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); @@ -23,27 +23,27 @@ let plugins = common.plugins; const indexPath = path.join(__dirname, conf.APPDIR, conf.SRC, 'index.html'); if (fs.existsSync(indexPath)) { - plugins.push( - new HtmlWebpackPlugin({ - publicPath: '', - template: path.join(conf.APPDIR, conf.SRC, 'index.html'), - templateParameters: { - NODE_ENV: 'development', - GRAPHQL_URL: conf['GRAPHQL_URL'], - STATIC_URL: conf['STATIC_URL'], - REACT_SCRIPTS: '', + plugins.push( + new HtmlWebpackPlugin({ + publicPath: '', + template: path.join(conf.APPDIR, conf.SRC, 'index.html'), + templateParameters: { + NODE_ENV: 'development', + GRAPHQL_URL: conf['GRAPHQL_URL'], + STATIC_URL: conf['STATIC_URL'], + REACT_SCRIPTS: '', }, }), - ); + ); } const config = merge(common.webpack, { entry: { - /*hot: [ - 'react-hot-loader/patch', - 'webpack-dev-server/?https://' + conf.HOSTNAME + ':' + conf.PORT, - 'webpack/hot/only-dev-server', - ],*/ + /*hot: [ + 'react-hot-loader/patch', + 'webpack-dev-server/?https://' + conf.HOSTNAME + ':' + conf.PORT, + 'webpack/hot/only-dev-server', + ],*/ }, output: { @@ -51,10 +51,10 @@ const config = merge(common.webpack, { filename: '[name].js', // necessary for HMR to know where to load the hot update chunks publicPath: `http${conf['HTTPS'] ? 's' : ''}://${conf['HOSTNAME']}:${conf.PORT}/`, - }, + }, module: { - rules: [{ + rules: [{ test: /\.tsx?$/, loader: 'ts-loader' }, { test: /\.jsx?$/, //exclude: /node_modules/, use: { @@ -77,42 +77,42 @@ const config = merge(common.webpack, { ], cacheDirectory: true, cacheCompression: true,*/ - }, - }, - }, + }, + }, + }, { test: /\.s?css$/, use: [{ loader: MiniCssExtractPlugin.loader, - }, + }, { loader: 'css-loader', options: { sourceMap: true, - }, - }, + }, + }, { loader: 'resolve-url-loader', - }, + }, { loader: 'sass-loader', options: { sourceMap: true, - }, - }, ], - }, + }, + },], + }, { test: /fontawesome([^.]+).(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, - type: "asset/resource", - }, + type: 'asset/resource', + }, { test: /\.(gif|png|jpg|jpeg|ttf|otf|eot|svg|webp|woff(2)?)$/, - type: "asset/resource", - }, { + type: 'asset/resource', + }, { test: /\.(png|webp|jpg|jpeg|gif|svg)$/, - type: "asset/resource", - }, ], - }, + type: 'asset/resource', + },], + }, plugins: plugins, mode: 'development', @@ -130,8 +130,8 @@ const config = merge(common.webpack, { 'Access-Control-Allow-Origin': '*', 'Referrer-Policy': 'unsafe-url', 'service-worker-allowed': '/', - }, - }, -}); + }, + }, + }); module.exports = config;