Skip to content

Instantly share code, notes, and snippets.

@Khauri
Last active July 14, 2020 23:57
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 Khauri/59125177c32b1024e9385fc00bda11d2 to your computer and use it in GitHub Desktop.
Save Khauri/59125177c32b1024e9385fc00bda11d2 to your computer and use it in GitHub Desktop.
require('dotenv').config();
const path = require('path');
const webpack = require('webpack');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const MarkoPlugin = require('@marko/webpack/plugin').default;
const CSSExtractPlugin = require('mini-css-extract-plugin');
const nodeExternals = require('webpack-node-externals');
const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer');
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const merge = require('webpack-merge');
const SpawnServerPlugin = require('spawn-server-webpack-plugin')
// Constants
const {NODE_ENV, BUNDLE_ANALYZER_MODE, PORT} = process.env;
const IS_PRODUCTION = /production/.test(NODE_ENV);
const IS_DEVELOPMENT = !IS_PRODUCTION;
// Plugins
const markoPlugin = new MarkoPlugin();
const spawnedServer = new SpawnServerPlugin({args: ['--experimental-worker', '--use-strict']});
const smp = new SpeedMeasurePlugin({disable: true, outputTarget: './smp.txt'});
// Common config (this is a function so that plugins return unique instances)
const commonConfig = () => ({
stats: 'minimal',
optimization: {
nodeEnv: false,
noEmitOnErrors: true,
},
mode: IS_PRODUCTION ? 'production' : 'development',
devtool: IS_PRODUCTION ? 'cheap-module-source-map' : 'inline-cheap-module-source-map',
// Configuration for the dev server
devServer: IS_DEVELOPMENT ? {
stats: 'minimal',
...spawnedServer.devServerConfig,
} : undefined,
output: {publicPath: '/static/'},
resolve: {
extensions: ['.js', '.json', '.marko'],
},
module: {
rules: [
{
test: /\.marko$/,
loader: '@marko/webpack/loader',
},
{
test: /\.svg$/,
loader: 'svg-url-loader',
},
// if a config doesn't have a css loader this willl hopefully output it as a client file when required
{
test: /\.(jpe?g|gif|png|eot|woff2?|ttf|s?css)$/,
loader: 'file-loader',
options: {
// File assets from server & browser compiler output to client folder.
outputPath: '../client',
publicPath: '/static/',
},
},
],
},
plugins: [
IS_PRODUCTION && new CleanWebpackPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
BUNDLE_ANALYZER_MODE && new BundleAnalyzerPlugin({analyzerMode: BUNDLE_ANALYZER_MODE}),
].filter(Boolean),
});
const clientConfig = {
name: 'Client',
optimization: {
// This configuration optimizes our common bundles
splitChunks: {
chunks: 'all',
maxSize: 300000,
},
},
module: {
rules: [
// css on the client is compiled
{
test: /\.s?css$/,
use: [
CSSExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
],
},
]
},
// Determines the location of the client output
output: {
filename: `[name]${IS_PRODUCTION ? '[chunkhash:8]' : ''}.js`,
path: path.join(__dirname, 'dist/client'),
},
plugins: [
IS_DEVELOPMENT && new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({'process.browser': true}),
new CSSExtractPlugin({filename: `[name]${IS_PRODUCTION ? '[chunkhash:8]' : ''}.css`}),
markoPlugin.browser,
].filter(Boolean),
};
const serverConfig = {
name: 'Server',
entry: './index.js',
target: 'async-node',
optimization: {minimize: false},
output: {
libraryTarget: 'commonjs2',
path: path.join(__dirname, 'dist/server'),
},
externals: [
nodeExternals({allowlist: [/\.(?!(?:jsx?|json)$).{1,5}$/i]}),
],
plugins: [
new webpack.DefinePlugin({
'process.browser': undefined,
'process.env.BUNDLE': true,
}),
new webpack.BannerPlugin({
entryOnly: true,
banner: 'require(\'source-map-support\').install();',
include: /\.js$/,
raw: true,
}),
IS_DEVELOPMENT && spawnedServer,
markoPlugin.server,
].filter(Boolean),
};
module.exports = smp.wrap([clientConfig, serverConfig].map(config => merge(commonConfig(), config)));
@Khauri
Copy link
Author

Khauri commented Jul 14, 2020

This config is based on https://github.com/marko-js-samples/marko-webpack/blob/master/webpack.config.js with a few changes.

I have a server entrypoint at index.js, and when css files are required on the server it generates a main.css file in the dist/server folder, which gets listed as an output file for the main entrypoint, causing spawn-server to try and run it, which throws an error. To solve this I just used the file-loader instead of the css-loaders on the server and let the css get placed in dist/client.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment