Bundling/Compiling Assets
We as a college have decided to use webpack as our bundler of choice. That is not to say that some legacy code won't use something else, like parcel, grunt or gulp, but in general if we are developing new software that contains javascript, SCSS or assets to be compiled/bundled, we will try to use webpack.
At this point, we're exploring Laravel Mix as a simplified abstraction for common webpack configuration with hopes that it can be our go-to for webpack configuration going forward. The reason for this is that it has a simple and intuitive syntax and covers the majority of cases we will need.
Older documentation below:
With WordPress, all functionality is broken up into plugins and themes, so each theme and plugin needs to have its own
webpack.config.js
file, if required. Below is an example of working config file for WordPress themes/plugins:const webpack = require('webpack');
const path = require("path");
const autoprefixer = require("autoprefixer");
const WebpackNotifierPlugin = require("webpack-notifier");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const currentDir = path.resolve(process.cwd());
const postcssLoader = {
loader: "postcss-loader",
options: {
plugins: () => [autoprefixer()]
}
};
let config = {
mode: "development",
entry: {
app: ["./src/index.js"]
},
output: {
path: currentDir + '/dist',
},
module: {
rules: [
{
test: /\.css$/,
oneOf: [
{
resourceQuery: /^\?raw$/,
use: ["style-loader", "css-loader"]
},
{
loaders: [
"style-loader",
{
loader: "css-loader",
options: { modules: true, importLoaders: 2 }
},
postcssLoader,
"sass-loader"
]
}
]
},
{
test: /\.less$/,
loaders: [
"style-loader",
"css-loader",
postcssLoader,
"less-loader"
]
},
{
test: /\.scss$/,
loaders: [
"style-loader",
"css-loader",
postcssLoader,
"sass-loader"
]
},
{
test: /\.(jpg|png|gif|svg)$/,
loaders: {
loader: "url-loader",
options: {
limit: 5000,
name: "[name]-[hash].[ext]"
}
}
},
{
test: /\.(ttf|eot|woff|woff2|mp3)$/,
loaders: ["file-loader"]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
cacheDirectory: true,
babelrc: false,
presets: [
require.resolve(
"@colbycommunications/babel-preset-colby"
)
]
}
}
}
]
},
plugins: [
// Clean build folder
new CleanWebpackPlugin(),
// Show notifications
new WebpackNotifierPlugin()
],
resolve: {
modules: [
"node_modules",
path.resolve("./"),
path.resolve("./node_modules")
],
mainFields: ["browser", "main", "module"],
extensions: [".js", ".json"]
},
optimization: {
noEmitOnErrors: true
}
};
if (process.env.NODE_ENV === "production") {
config = {
mode: "production",
entry: {
app: ["./src/index.js"]
},
output: {
path: currentDir + '/dist',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
cacheDirectory: true,
babelrc: false,
presets: [
require.resolve(
"@colbycommunications/babel-preset-colby"
)
]
}
}
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: "css-loader", options: { minimize: true } },
postcssLoader,
"sass-loader"
]
},
{
test: /\.css$/,
oneOf: [
{
resourceQuery: /^\?raw$/,
use: ["style-loader", "css-loader"]
},
{
loaders: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 2,
minimize: true
}
},
postcssLoader,
"sass-loader"
]
}
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ["file-loader"]
}
]
},
plugins: [
// Clean build folder
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: "app.bundle.css"
})
],
resolve: {
modules: [
"node_modules",
path.resolve("./"),
path.resolve("./node_modules")
],
mainFields: ["browser", "main", "module"],
extensions: [".js", ".json"]
},
optimization: {
noEmitOnErrors: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
ecma: 6
}
}),
new OptimizeCSSAssetsPlugin({})
]
}
};
}
module.exports = config;
Laravel comes with all the scaffolding you need to build javascript components in react and bundle assets with webpack. Each Laravel app comes with a
webpack.mix.js
file where you can add your specific configuration. Here is an example of working config file:const mix = require("laravel-mix");
const path = require("path");
const autoprefixer = require("autoprefixer");
const WebpackNotifierPlugin = require("webpack-notifier");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const currentDir = path.resolve(process.cwd());
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
const postcssLoader = {
loader: "postcss-loader",
options: {
plugins: () => [autoprefixer()]
}
};
const sassLoader = {
loader: "sass-loader",
options: {
includePaths: [
path.resolve("."),
path.resolve("./resources/assets/sass")
]
}
};
let config = {
mode: "development",
entry: {
app: ["./resources/js/app.js"]
},
output: {
path: currentDir + "/public/build",
filename: "[name].bundle.js"
},
module: {
rules: [
{
test: /\.css$/,
oneOf: [
{
resourceQuery: /^\?raw$/,
use: ["style-loader", "css-loader"]
},
{
loaders: [
"style-loader",
{
loader: "css-loader",
options: { modules: true, importLoaders: 2 }
},
postcssLoader,
sassLoader
]
}
]
},
{
test: /\.less$/,
loaders: [
"style-loader",
"css-loader",
postcssLoader,
"less-loader"
]
},
{
test: /\.scss$/,
loaders: [
"style-loader",
"css-loader",
postcssLoader,
sassLoader
]
},
{
test: /\.(jpg|png|gif|svg)$/,
loaders: {
loader: "url-loader",
options: {
limit: 5000,
name: "[name]-[hash].[ext]"
}
}
},
{
test: /\.(ttf|eot|woff|woff2|mp3)$/,
loaders: ["file-loader"]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
cacheDirectory: true,
babelrc: false,
presets: [
require.resolve(
"@colbycommunications/babel-preset-colby"
)
]
}
}
}
]
},
plugins: [
// Clean build folder
new CleanWebpackPlugin(),
// Show notifications
new WebpackNotifierPlugin()
],
resolve: {
modules: [
"node_modules",
path.resolve("./"),
path.resolve("./resources/assets"),
path.resolve("./node_modules")
],
alias: {
// Use this libraries always from this location
react: path.resolve("./node_modules/react"),
"react-dom": path.resolve("./node_modules/react-dom")
},
mainFields: ["browser", "main", "module"],
extensions: [".js", ".json"]
},
optimization: {
noEmitOnErrors: true
}
};
if (process.env.NODE_ENV === "production") {
config = {
mode: "production",
entry: {
app: ["./resources/js/app.js"]
},
output: {
path: currentDir + "/public/build",
filename: "[name].bundle.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
cacheDirectory: true,
babelrc: false,
presets: [
require.resolve(
"@colbycommunications/babel-preset-colby"
)
]
}
}
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: "css-loader", options: { minimize: true } },
postcssLoader,
sassLoader
]
},
{
test: /\.css$/,
oneOf: [
{
resourceQuery: /^\?raw$/,
use: ["style-loader", "css-loader"]
},
{
loaders: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 2,
minimize: true
}
},
postcssLoader,
sassLoader
]
}
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ["file-loader"]
}
]
},
plugins: [
// Clean build folder
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: "app.bundle.css"
})
],
resolve: {
modules: [
"node_modules",
path.resolve("./"),
path.resolve("./node_modules")
],
mainFields: ["browser", "main", "module"],
extensions: [".js", ".json"]
},
optimization: {
noEmitOnErrors: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
ecma: 6
}
}),
new OptimizeCSSAssetsPlugin({})
]
}
};
}
mix.webpackConfig(config);
In our plugins, themes, packages, we want to build bundle files or other assets into a
dist
directory.If you want to load
css-modules
and global css files simultaneously, the best way is to use in webpack.config.js
:{
test: /\.css$/,
oneOf: [
{
resourceQuery: /^\?raw$/,
use: ["style-loader", "css-loader"]
},
{
loaders: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 2,
minimize: true
}
},
postcssLoader,
sassLoader
]
}
]
},
where
resourceQuery: /^\?raw$/
will load global stylesheets from dependencies as raw CSS. For example, when you import stylesheets from dependencies, you should format them like this: import "froala-editor/css/froala_style.min.css?raw"
This way, webpack will know to read the file as raw CSS instead of trying to do a bunch of css-module things.
Last modified 1yr ago