Skip to content

Instantly share code, notes, and snippets.

@dgrigg
Created May 30, 2019 18:19
Show Gist options
  • Save dgrigg/d4811ee9bc85d31376f4cb7365abf04d to your computer and use it in GitHub Desktop.
Save dgrigg/d4811ee9bc85d31376f4cb7365abf04d to your computer and use it in GitHub Desktop.
Webpack + Twig setup
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const WebpackNotifierPlugin = require('webpack-notifier');
const TailwindCss = require('tailwindcss');
const AutoPrefixer = require('autoprefixer');
const path = require('path');
const fs = require('fs');
const purgecss = require('@fullhuman/postcss-purgecss')({
// Specify the paths to all of the template files in your project
content: [
'./src/**/*.twig',
'./src/**/*.js',
'./node_modules/slick-carousel/slick/slick.js',
],
// Include any special characters you're using in this regular expression
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [],
});
// create a list of twig files to generate
// filter out anything that starts with an underscore or is not a twig file
function walk(dir) {
let results = [];
const list = fs.readdirSync(dir);
list.forEach(file => {
file = `${dir}/${file}`;
const stat = fs.statSync(file);
if (stat && stat.isDirectory() && path.basename(file).indexOf('_') !== 0) {
/* Recurse into a subdirectory */
results = results.concat(walk(file));
} else if (
stat &&
!stat.isDirectory() &&
path.extname(file) === '.twig' &&
path.basename(file).indexOf('_') !== 0
) {
/* Is a file */
results.push(file);
}
});
return results;
}
const files = walk('./src/twig');
// generates html plugins to export
const htmlPlugins = files.map(
file =>
// Create new HTMLWebpackPlugin with options
new HtmlWebpackPlugin({
filename: file.replace('./src/twig/', '').replace('.twig', '.html'),
template: path.resolve(__dirname, file),
hash: true,
})
);
module.exports = {
stats: {
entrypoints: false,
children: false,
},
context: path.resolve(__dirname, 'src'),
entry: {
main: './js/main.js',
},
output: {
publicPath: '/',
path: path.join(__dirname, './web'),
filename: '[name].[hash].js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
},
],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development',
},
},
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: loader => [
TailwindCss,
AutoPrefixer,
...(process.env.NODE_ENV == 'production' ? [purgecss] : []),
],
},
},
'sass-loader',
],
},
{
test: /\.(woff2?|ttf|eot|svg)(\?.*)?$/i,
use: 'file-loader?name=fonts/[name].[hash].[ext]',
},
// Twig templates
{
test: /\.twig$/,
use: [
'raw-loader',
{
loader: 'twig-html-loader',
options: {
data: {},
},
},
],
},
],
},
plugins: [
new WebpackNotifierPlugin({ alwaysNotify: true }),
// inject into files
new webpack.ProvidePlugin({
jQuery: 'jquery',
jquery: 'jquery',
$: 'jquery',
'window.jQuery': 'jQuery',
}),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].[hash].css',
chunkFilename: '[id].css',
}),
new CopyWebpackPlugin([{ from: './assets', to: './assets' }]),
new CleanWebpackPlugin({
protectWebpackAssets: true,
cleanOnceBeforeBuildPatterns: [],
cleanAfterEveryBuildPatterns: [
'*.js',
'*.css',
'*.map',
'.html',
'!uploads/**',
'!assets/**',
],
}),
new ManifestPlugin({
filter: ({ name }) => name.endsWith('.js') || name.endsWith('.css'),
}),
].concat(htmlPlugins),
watch: false,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment