349 lines
8.0 KiB
JavaScript
349 lines
8.0 KiB
JavaScript
/* eslint-disable import/no-extraneous-dependencies */
|
|
const webpack = require('webpack');
|
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // installed via npm
|
|
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
|
const TerserPlugin = require('terser-webpack-plugin');
|
|
// const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
|
|
const ImageminPlugin = require('imagemin-webpack-plugin').default;
|
|
|
|
const CompressionPlugin = require('compression-webpack-plugin');
|
|
const zlib = require('zlib');
|
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
|
|
const merge = require('webpack-merge');
|
|
// local
|
|
const paths = require('../paths');
|
|
|
|
/*
|
|
Need to load the configs here so they can be applied to the external folders as wells
|
|
*/
|
|
const babelConfig = require('../../babel.config');
|
|
// Need required in the file for parent files
|
|
const postcssConfig = require('../../postcss.config');
|
|
|
|
/**
|
|
* Resolve paths
|
|
*/
|
|
exports.modulePathResolve = (srcList, modulesList) => ({
|
|
resolve: {
|
|
modules: [...srcList, ...modulesList],
|
|
extensions: ['*', '.js', '.jsx', '.ts', '.tsx', '.json', '.mjs', '.gql', '.graphql'],
|
|
},
|
|
resolveLoader: {
|
|
modules: modulesList,
|
|
},
|
|
});
|
|
/**
|
|
* Clean
|
|
*/
|
|
exports.clean = (path, root) => ({
|
|
plugins: [new CleanWebpackPlugin()],
|
|
});
|
|
|
|
/**
|
|
* JS (see also .babelrc)
|
|
*/
|
|
exports.loadJavaScript = ({ include, exclude, prod } = {}) => ({
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.(js|jsx|ts|mjs|tsx)$/,
|
|
include,
|
|
// node_modules(?!([\\/](attr-accept|moment)))
|
|
exclude: exclude || /node_modules/,
|
|
use: [
|
|
{
|
|
loader: 'babel-loader',
|
|
options: {
|
|
presets: babelConfig.presets,
|
|
plugins: prod ? babelConfig.plugins.concat('transform-remove-console') : babelConfig.plugins,
|
|
},
|
|
// */
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
/**
|
|
* Default output path
|
|
*/
|
|
exports.outputPath = ({
|
|
path = paths.defaultBuild,
|
|
filename = '[name].js',
|
|
chunkFilename = '[name].[contenthash].js',
|
|
publicPath = paths.publicPath,
|
|
} = {}) => ({
|
|
output: {
|
|
path,
|
|
filename,
|
|
chunkFilename,
|
|
// This option specifies the public URL of the output directory when referenced in a browser. A relative URL is resolved relative to the HTML page (or <base> tag).
|
|
publicPath,
|
|
// https://github.com/webpack/webpack/issues/11660
|
|
// addition for webpack 5
|
|
// chunkLoading: false,
|
|
// wasmLoading: false,
|
|
},
|
|
});
|
|
|
|
/**
|
|
* (S)CSS
|
|
*/
|
|
exports.loadCSS = ({ include, exclude, prod = false, styleLoader = false, server = false } = {}) => {
|
|
const fileName = prod ? '[name].[contenthash].css' : '[name].css';
|
|
|
|
// use style loader in dev (no ssr)
|
|
const useStyleLoader = styleLoader;
|
|
|
|
const pluginOptions = {
|
|
filename: fileName,
|
|
ignoreOrder: !prod, // Enable to remove warnings about conflicting order
|
|
};
|
|
|
|
const plugin = new MiniCssExtractPlugin(pluginOptions);
|
|
|
|
const loaderOptions = {
|
|
// disabling esModule prevent from having warning for empty css files => should not be disabled in prod
|
|
esModule: prod,
|
|
};
|
|
|
|
const usages = [
|
|
{
|
|
loader: 'css-loader',
|
|
options: {
|
|
sourceMap: true,
|
|
// The option importLoaders allows you to configure how many loaders before css-loader should be applied to @imported resources.
|
|
importLoaders: 2,
|
|
// to use with localIdentName
|
|
modules: {
|
|
localIdentName: '[local]--[hash:base64:5]',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
loader: 'postcss-loader',
|
|
options: {
|
|
postcssOptions: postcssConfig,
|
|
},
|
|
},
|
|
{
|
|
loader: 'sass-loader',
|
|
options: {},
|
|
},
|
|
];
|
|
|
|
if (!server) {
|
|
// if not loaded on server part, module styleIdentifiers will not be usable in the server
|
|
usages.unshift({
|
|
loader: useStyleLoader ? 'style-loader' : MiniCssExtractPlugin.loader,
|
|
options: loaderOptions,
|
|
});
|
|
}
|
|
return {
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.(css|sass|scss)$/,
|
|
include,
|
|
exclude,
|
|
use: usages,
|
|
},
|
|
],
|
|
},
|
|
plugins: [plugin],
|
|
};
|
|
};
|
|
|
|
exports.setVariables = obj => {
|
|
const env = {};
|
|
const keys = Object.keys(obj);
|
|
for (let i = 0; i < keys.length; i += 1) {
|
|
const key = keys[i];
|
|
const value = obj[key];
|
|
env[key] = JSON.stringify(value);
|
|
}
|
|
return {
|
|
plugins: [new webpack.DefinePlugin(env)],
|
|
};
|
|
};
|
|
|
|
/**
|
|
* FONTS
|
|
*/
|
|
const FONTLIST = [
|
|
['woff', 'application/font-woff'],
|
|
['woff2', 'application/font-woff2'],
|
|
['otf', 'font/opentype'],
|
|
['ttf', 'application/octet-stream'],
|
|
['eot', 'application/vnd.ms-fontobject'],
|
|
['svg', 'image/svg+xml'],
|
|
];
|
|
|
|
exports.loadFonts = () => {
|
|
let rsltConf = {
|
|
module: {
|
|
rules: [],
|
|
},
|
|
};
|
|
|
|
FONTLIST.forEach(font => {
|
|
const extension = font[0];
|
|
const mimetype = font[1];
|
|
|
|
const rule = {
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: new RegExp(`\\.${extension}$`),
|
|
loader: 'file-loader',
|
|
include: [/fonts?/],
|
|
options: {
|
|
name: 'fonts/[name].[ext]',
|
|
// limit: 10000,
|
|
mimetype,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
};
|
|
rsltConf = merge(rsltConf, rule);
|
|
});
|
|
|
|
return rsltConf;
|
|
};
|
|
|
|
/**
|
|
* Images
|
|
*/
|
|
exports.loadImages = () => ({
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.(png|jpe?g|gif|svg|ico)$/,
|
|
loader: 'file-loader',
|
|
exclude: [/fonts?/],
|
|
options: {
|
|
name: 'images/[name].[contenthash].[ext]',
|
|
// for url loader
|
|
// limit: 8192,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
/**
|
|
* Images
|
|
*/
|
|
exports.loadVideos = () => ({
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.(mp4|mov)$/,
|
|
loader: 'file-loader',
|
|
options: {
|
|
name: 'videos/[name].[contenthash].[ext]',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
// Idea of splitting vendors
|
|
exports.optimize = () => ({
|
|
// https://webpack.js.org/plugins/compression-webpack-plugin/
|
|
plugins: [
|
|
// new CompressionPlugin({
|
|
// filename: '[path][base].br',
|
|
// algorithm: 'brotliCompress',
|
|
// test: /\.(js|css|html|svg)$/,
|
|
// compressionOptions: {
|
|
// params: {
|
|
// [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
|
|
// },
|
|
// },
|
|
// threshold: 10240,
|
|
// minRatio: 0.8,
|
|
// deleteOriginalAssets: false,
|
|
// }),
|
|
],
|
|
optimization: {
|
|
minimizer: [
|
|
new TerserPlugin({
|
|
terserOptions: {
|
|
safari10: true,
|
|
},
|
|
}),
|
|
new OptimizeCSSAssetsPlugin({}),
|
|
],
|
|
// use default splitChunks config with chnks all
|
|
// https://webpack.js.org/plugins/split-chunks-plugin/#optimizationsplitchunks
|
|
splitChunks: {
|
|
chunks: 'all',
|
|
// cacheGroups: {
|
|
// vendor: {
|
|
// // test with exclusion : /[\\/]node_modules[\\/](?!(attr-accept|moment))/
|
|
// test: /[\\/]node_modules[\\/]/,
|
|
// name: 'vendor',
|
|
// },
|
|
// },
|
|
},
|
|
// Source : create-react-app
|
|
// Keep the runtime chunk separated to enable long term caching
|
|
// https://twitter.com/wSokra/status/969679223278505985
|
|
// https://github.com/facebook/create-react-app/issues/5358
|
|
runtimeChunk: {
|
|
name: entrypoint => `runtime-${entrypoint.name}`,
|
|
},
|
|
},
|
|
});
|
|
|
|
// Text loader
|
|
exports.loadTxts = () => ({
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.txt$/i,
|
|
use: 'raw-loader',
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
// GraphQL loader
|
|
exports.loadGQL = () => ({
|
|
module: {
|
|
rules: [
|
|
// fixes https://github.com/graphql/graphql-js/issues/1272
|
|
{
|
|
test: /\.mjs$/,
|
|
include: /node_modules/,
|
|
type: 'javascript/auto',
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
exports.imageOptimization = () => ({
|
|
plugins: [new ImageminPlugin({ test: /\.(jpe?g|png|gif)$/i })],
|
|
});
|
|
|
|
// Add stats
|
|
exports.stats = () => ({
|
|
// To discover
|
|
stats: {
|
|
cached: false,
|
|
cachedAssets: false,
|
|
chunks: false,
|
|
chunkModules: false,
|
|
colors: true,
|
|
hash: false,
|
|
modules: false,
|
|
reasons: false,
|
|
timings: true,
|
|
version: false,
|
|
},
|
|
});
|