I am trying to get Webpack to render a static html and export relative css, starting from a pug template and css modules using HtmlWebpackPlugin.
My setup is as follow
//webpack.config.js
...
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: "src/templates/index.pug",
excludeChunks: ["landing", "runtime"],
excludeAssets: [/index.*.js/]
})
new HtmlWebpackExcludeAssetsPlugin(),
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
chunkFilename: "[name].[contenthash].css"
})
]
module: {
rules: [
/**
* pug
*/
{
test: /\.pug$/,
exclude: /node_modules/,
use: ["pug-loader"]
},
/**
* scss
*/
{
test: /\.scss$/,
exclude: /node_modules|_.+.scss/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === "development"
}
},
{
loader: "css-loader",
options: {
modules: true,
localsConvention: "camelCase",
sourceMap: true
}
},
"postcss-loader",
"sass-loader"
]
}
]
}
...
Then in my index.pug file I would like to do something like this:
- var styles = require("../styles/style.module.scss")
div(class=styles.someClass)
The problem is that if I leave the configuration as is, I get
ERROR in ./src/styles/style.module.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
TypeError: this[MODULE_TYPE] is not a function
I managed to correctly get the transformed class names in the pug template by doing
/**
* scss
*/
{
test: /\.scss$/,
exclude: /node_modules|_.+.scss/,
use: [
//{
// loader: MiniCssExtractPlugin.loader,
// options: {
// hmr: process.env.NODE_ENV === "development"
// }
//},
{
loader: "css-loader",
options: {
modules: true,
localsConvention: "camelCase",
sourceMap: true,
onlyLocals: true <=====
}
},
"postcss-loader",
"sass-loader"
]
}
But by removing MiniCssExtractLoader from the chain I obviously don't get the exported css file.
By setting onlyLocals: true
, classes in pug work as expected because css-loader exports the mappings.
If I remove - var styles = require("../styles/style.module.scss")
from pug template and leave MiniCssExtractPlugin in the loaders' chain I get the opposite: css file, but no mappings.
Any idea? Is there a way to export the css file and get mappings back directly in the pug template?
P.S. I have also come across this example from pug-loader's GitHub page
var template = require("pug-loader!./file.pug");
// => returns file.pug content as template function
// or, if you've bound .pug to pug-loader
var template = require("./file.pug");
var locals = { /* ... */ };
var html = template(locals);
// => the rendered HTML
Thought template(locals)
would inject the locals into the template but I might have misinterpreted, since the html returned have unchanged classes' names, thus problem persists.
Just found out, all it takes is inlining the loaders applied in the pug template
- var styles = require("!css-loader?modules&onlyLocals&localsConvention=camelCase!postcss-loader!sass-loader!../styles/style.module.scss")
and having the Webpack configuration to export the css file
entry: {
index: ["./src/styles/style.module.scss"]
},
module: {
rules: [
/**
* scss
*/
{
test: /\.scss$/,
exclude: /node_modules|_.+.scss/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === "development"
}
},
{
loader: "css-loader",
options: {
modules: true
}
},
"postcss-loader",
"sass-loader"
]
}
]
},
If anyone knows a better solution to make use of source maps please post it.