This commit is contained in:
2020-05-17 13:56:21 +03:00
commit e9a41ffc22
32 changed files with 10191 additions and 0 deletions

4
webpack/Environment.js Normal file
View File

@@ -0,0 +1,4 @@
module.exports = {
development: 'development',
production: 'production',
};

20
webpack/paths.js Normal file
View File

@@ -0,0 +1,20 @@
const path = require('path');
const root = '../';
module.exports = {
root: path.resolve(__dirname, root),
outputPath: path.resolve(__dirname, root, 'build'),
entryPath: path.resolve(__dirname, root, 'src/index.jsx'),
source: path.resolve(__dirname, root, 'src/'),
templatePath: path.resolve(__dirname, root, 'public/template.html'),
cachePath: path.join(process.cwd(), 'node_modules/.cache/hard-source/', '[confighash]'),
publicPath: './',
assetPath: 'assets',
assetOriginPath: 'public/assets/',
scriptsPath: 'scripts',
imagesFolder: 'images',
fontsFolder: 'fonts',
cssFolder: 'css',
jsFolder: 'js',
};

122
webpack/webpack.common.js Normal file
View File

@@ -0,0 +1,122 @@
/* eslint-disable import/no-extraneous-dependencies */
const { ProgressPlugin } = require('webpack');
const convert = require('koa-connect');
const history = require('connect-history-api-fallback');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const commonPaths = require('./paths');
const Environment = require('./Environment');
module.exports = {
mode: Environment[process.env.NODE_ENV],
entry: commonPaths.entryPath,
module: {
rules: [
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
exclude: /(node_modules)/,
options: {
presets: ['@babel/preset-env'],
},
},
{
enforce: 'pre',
test: /\.(js|jsx)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/,
options: {
emitWarning: process.env.NODE_ENV !== Environment.production,
},
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: commonPaths.imagesFolder,
},
},
],
},
{
test: /\.(woff2|ttf|woff|eot)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: commonPaths.fontsFolder,
},
},
],
},
],
},
serve: {
add: (app) => {
app.use(convert(history()));
},
content: commonPaths.entryPath,
dev: {
publicPath: commonPaths.outputPath,
},
open: false,
},
resolve: {
modules: ['src', 'node_modules'],
extensions: ['*', '.js', '.jsx', '.css', '.scss'],
},
plugins: [
new ProgressPlugin(),
new HtmlWebpackPlugin({
template: commonPaths.templatePath,
}),
new HardSourceWebpackPlugin({
// Either an absolute path or relative to webpack's options.context.
cacheDirectory: commonPaths.cachePath,
// Either a string of object hash function given a webpack config.
// node-object-hash on npm can be used to build this.
configHash: (webpackConfig) => require('node-object-hash')({ // eslint-disable-line
sort: false,
}).hash(webpackConfig),
// Either false, a string, an object, or a project hashing function.
environmentHash: {
root: process.cwd(),
directories: [],
files: [
// Cache will get an unique hash based on those files
// if either of them changes, new cache must be generated
'package-lock.json',
'.babelrc.js',
],
},
info: {
mode: 'none',
level: 'debug',
},
// Clean up large, old caches automatically.
cachePrune: {
// Caches younger than `maxAge` are not considered for deletion.
// They must be at least this old in milliseconds.
maxAge: 3 * 60 * 60 * 1000, // 3 hours
// All caches together must be larger than `sizeThreshold` before any
// caches will be deleted.
// Together they must be at least this big in bytes.
sizeThreshold: 50 * 1024 * 1024, // 50 MB
},
}),
new ScriptExtHtmlWebpackPlugin({
defaultAttribute: 'async',
}),
new CopyWebpackPlugin({
patterns: [{
from: commonPaths.assetOriginPath,
to: commonPaths.assetPath,
}],
}),
],
};

57
webpack/webpack.dev.js Normal file
View File

@@ -0,0 +1,57 @@
/* eslint-disable import/no-extraneous-dependencies */
const { HotModuleReplacementPlugin } = require('webpack');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const commonPaths = require('./paths');
module.exports = {
devtool: 'cheap-eval-source-map',
output: {
filename: '[name].js',
path: commonPaths.outputPath,
chunkFilename: '[name].js',
},
module: {
rules: [
{
test: /\.(js|jsx)$/, // allows both .jsx and .js
exclude: /node_modules/,
include: commonPaths.source,
loader: 'babel-loader',
options: {
cacheDirectory: true,
plugins: ['react-hot-loader/babel'],
},
},
{
test: /\.(sa|sc|c)ss$/,
use: [{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
modules: false,
},
},
{
loader: 'sass-loader',
},
],
},
],
},
devServer: {
contentBase: commonPaths.outputPath,
compress: true,
hot: true,
port: 3000,
},
plugins: [
new HotModuleReplacementPlugin(),
new BundleAnalyzerPlugin({
analyzerPort: 8888,
openAnalyzer: false,
}),
],
};

98
webpack/webpack.prod.js Normal file
View File

@@ -0,0 +1,98 @@
/* eslint-disable import/no-extraneous-dependencies */
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const commonPaths = require('./paths');
module.exports = {
output: {
publicPath: commonPaths.publicPath,
filename: `${commonPaths.scriptsPath}/${commonPaths.jsFolder}/[name].[hash].js`,
path: commonPaths.outputPath,
chunkFilename: `${commonPaths.scriptsPath}/${commonPaths.jsFolder}/[name].[chunkHash].js`,
},
module: {
rules: [
{
test: /\.(js|jsx)$/, // allows both .jsx and .js
exclude: /node_modules/,
include: commonPaths.source,
use: [
{
loader: 'babel-loader',
},
],
},
{
test: /\.(sa|sc|c)ss$/,
enforce: 'pre',
use: [{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
modules: false
},
},
{
loader: 'sass-loader',
},
],
},
],
},
optimization: {
usedExports: true, // to remove unused exports
splitChunks: {
chunks: 'all',
automaticNameDelimiter: '.',
minSize: 30000,
},
noEmitOnErrors: true,
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true, // use multi-process parallel running to improve the build speed
sourceMap: false, // set to true if you want JS source maps
terserOptions: {
mangle: true, // pass false to skip mangling names
toplevel: false, // set to true if you wish to enable top level variable and function name mangling and to drop unused variables and functions
ie8: false, // set to true to support IE8.
keep_fnames: false, // pass true to prevent discarding or mangling of function names
output: {
comments: false,
},
},
}),
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessorPluginOptions: {
preset: [
'default',
{
discardComments: {
removeAll: true,
},
},
],
},
canPrint: true,
}),
],
},
plugins: [
new MiniCssExtractPlugin({
filename: `${commonPaths.assetPath}/${commonPaths.cssFolder}/[name].css`,
chunkFilename: '[id].css',
}),
new BundleAnalyzerPlugin({
generateStatsFile: true,
reportFilename: 'bundleReport.html',
analyzerMode: 'static',
}),
],
};