Skip to content

Instantly share code, notes, and snippets.

@mrdoinel
Created October 3, 2019 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrdoinel/b85cb55408f77de852f7909415d49046 to your computer and use it in GitHub Desktop.
Save mrdoinel/b85cb55408f77de852f7909415d49046 to your computer and use it in GitHub Desktop.
TTP Webpack config
const path = require('path');
const data = require('./frontend/manifest');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const entries = {};
// Scripts
// Dynamic entry points defined in the manifest with fallback on the default head.js and app.js
if (data.scripts) {
for (var key in data.scripts) {
const entryName = path.parse(key).name;
entries[entryName] = path.resolve(data.paths.source, data.scripts[key]);
}
}
// Styles
// Dynamic entry points defined in the manifest with fallback on the default app.scss and html4css.scss
if (data.styles) {
for (var key in data.styles) {
const entryName = path.parse(key).name;
entries[entryName] = path.resolve(data.paths.source, data.styles[key]);
}
}
module.exports = (env, argv) => {
const devMode = argv.mode && Boolean(argv.mode !== 'production');
const verboseMode = argv.verbosemode && Boolean(argv.verbosemode !== 'false');
const sourcePath = path.resolve(data.paths.source);
let defaultWebpackConfig = {
entry: entries,
output: {
filename: devMode ? '[name].js' : '[name].[chunkhash:8].js',
path: path.resolve(data.paths.dist),
},
resolve: {
alias: {
'@': sourcePath,
},
},
stats: verboseMode ? 'verbose' : {
children: false, // Shut up child plugin logs. Example: MiniCssExtractPlugin,
entrypoints: true,
// Set the maximum number of modules to be shown
maxModules: 15,
},
devtool: devMode ? 'source-map' : false,
module: {
rules: [
{
test: /\.js$/,
// exclude: /node_modules\/(?!(@antoine_a17|@gulp-sourcemaps|)\/).*/,
loader: require.resolve('babel-loader'),
options: {
presets: [require.resolve('@babel/preset-env')],
cacheDirectory: true
}
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 2,
url: true,
sourceMap: false,
},
},
{
loader: require.resolve('sass-loader'),
options: {
url: true,
sourceMap: false,
implementation: require('sass'), // dart-sass
},
},
],
},
{
test: /\.svg$/,
loader: 'file-loader',
options: {
name: devMode ? '[name].[ext]' : '[name].[contenthash].[ext]',
publicPath: data.paths.assets + data.paths.images,
outputPath: data.paths.images,
},
},
{
test: /\.(jpg|png|gif)$/,
loader: 'file-loader',
options: {
name: devMode ? '[name].[ext]' : '[name].[contenthash].[ext]',
publicPath: data.paths.assets + data.paths.images,
outputPath: data.paths.images,
},
},
{
// from file used like that "~@/fonts/Px-Grotesk-Bold.woff" inside .scss file
test: /\.(woff|woff2|ttf|eot|otf)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file-loader',
options: {
name: devMode ? '[name].[ext]' : '[name].[contenthash].[ext]',
publicPath: data.paths.assets + data.paths.fonts,
outputPath: data.paths.fonts,
},
},
],
},
optimization: {
minimizer: [
new TerserPlugin(),
new OptimizeCSSAssetsPlugin(),
],
},
plugins: [
new CleanWebpackPlugin({
root: path.resolve(),
verbose: verboseMode,
beforeEmit: true,
}),
new FixStyleOnlyEntriesPlugin(),
new MiniCssExtractPlugin({
filename: devMode ? `[name].css` : `[name].[contenthash].css`,
path: path.resolve(data.paths.dist),
}),
new CopyWebpackPlugin([
{
from: path.resolve(data.paths.source + 'images/'),
ignore: ['icons.svg'],
to: devMode ?
path.resolve(data.paths.dist + 'images/[name].[ext]') :
path.resolve(data.paths.dist + 'images/[name].[hash].[ext]'),
},
{
from: path.resolve(data.paths.source + 'images/icons.svg'),
to: devMode ?
path.resolve(data.paths.dist + 'icons/[name].[ext]') :
path.resolve(data.paths.dist + 'icons/[name].[hash].[ext]'),
},
]),
],
};
if (devMode) {
// Default BrowserSyncOptions
let defaultBrowserSyncConfig = {
ui: {port: 3001},
port: 3000,
snippetOptions: {
whitelist: data.config.whitelist,
blacklist: data.config.blacklist,
},
};
// Default BrowserSync config altered by the manifest.json
//
// Proxy : it will use the environment DEV_URL variable or the manifest.config.devUrl if set
if (data.config.devUrl) defaultBrowserSyncConfig.proxy = data.config.devUrl;
if (process.env.DEV_URL) defaultBrowserSyncConfig.proxy = process.env.DEV_URL;
// Port or the Browser Sync UI and port of the application
if (data.config.browsersyncUiPort) defaultBrowserSyncConfig.ui.port = data.config.browsersyncUiPort;
if (data.config.browsersyncPort) defaultBrowserSyncConfig.port = data.config.browsersyncPort;
defaultWebpackConfig.plugins.push(
new BrowserSyncPlugin(defaultBrowserSyncConfig, {reload: true}));
} else {
defaultWebpackConfig.plugins.push(new ManifestPlugin({
fileName: 'rev-manifest.json',
filter(file) {
return !file.name.includes('.keep');
},
map: (file) => {
file.name = file.name.replace(/(\.[a-f0-9]{32})(\..*)$/, '$2');
return file;
},
}));
}
return defaultWebpackConfig;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment