Reputation: 4492
I am relatively new to express + webpack, so i am unclear wether this is intended or not, and if not, how to properly configure it. the question is around the additional asset & entry point created when using the mini-css-extract-plugin.
webpack config:
Extract = require('mini-css-extract-plugin');
path = require('path');
Write = require('write-file-webpack-plugin');
module.exports = {
mode: 'development',
entry: {
demo_scripts: path.resolve('server', 'scripts', 'demo.js'),
demo_styles: path.resolve('server', 'styles', 'demo.css')
},
output: {
path: path.resolve('.tmp'),
filename: '[name].js'
},
plugins: [new Write(), new Extract()],
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['babel-preset-env']
}
}
]
},
{
test: /\.css/,
use: [
{
loader: Extract.loader
},
{
loader: 'css-loader'
}
]
}
]
}
};
webpack output
Asset Size Chunks Chunk Names
demo_scripts.js 3.91 KiB demo_scripts [emitted] demo_scripts
demo_styles.css 36 bytes demo_styles [emitted] demo_styles
demo_styles.js 3.89 KiB demo_styles [emitted] demo_styles
Entrypoint demo_scripts = demo_scripts.js
Entrypoint demo_styles = demo_styles.css demo_styles.js
my question is, why is demo_styles.js
being created? although the css is being extracted, it almost seems like webpack is still creating a bundled js with css, but when i view that file, the only line in it is
eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./server/styles/demo.css?");
can anyone help explain what is going on here?
UPDATE
if i remove the demo_styles entry point, and configure it via the plugin init, no css asset is built.
({
plugins: [
new Write(),
new Extract({
filename: 'demo_styles.css'
})
]
});
Asset Size Chunks Chunk Names
demo_scripts.js 3.91 KiB demo_scripts [emitted] demo_scripts
Entrypoint demo_scripts = demo_scripts.js
the repo for this is here (note the express branch) https://github.com/brewster1134/bumper/tree/express
Upvotes: 7
Views: 6615
Reputation: 11
After fidgeting with the same problem for a while, I cooked up a solution that leverages the afterEmit
hook in Webpack and removes unwanted JS blanks after they are emitted.
Here's what you can do:
Step 1
Add a custom plugin that hooks to afterEmit
and removes the unwanted files. The list of the files should be provided to the plugin constructor. You can add the plugin to webpack.config.js
directly, but I found it more convenient to author in a separate module – in my case I created it under webpack-custom-plugins/remove-unwanted-files.js
:
const path = require('path');
const fs = require('fs');
class RemoveUnwantedFilesPlugin {
constructor(filesToRemove) {
this.filesToRemove = filesToRemove;
}
apply(compiler) {
compiler.hooks.afterEmit.tap('RemoveUnwantedFilesPlugin', (compilation) => {
this.filesToRemove.forEach((file) => {
const filePath = path.join(compilation.outputOptions.path, file);
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
});
});
}
}
module.exports = RemoveUnwantedFilesPlugin
Step 2
Import the plugin into webpack.config.js
...
const RemoveUnwantedFilesPlugin = require('./webpack-custom-plugins/remove-unwanted-files');
...and register it:
plugins: [
// ...
new RemoveUnwantedFilesPlugin(['demo_styles.js']),
],
This should solve your problem for a single CSS input. If you need to remove blank JS files from all standalone SCSS/CSS entries, I'd suggest authoring a snippet that filters your list of inputs and retains the ones that only contain stylesheet files. You can then pass the filtered list to the RemoveUnwantedFilesPlugin
constructor to get rid of all blanks at once.
Upvotes: 1
Reputation: 835
Webpack pulls everything into a js file, then MiniCssExtractPlugin takes it out of that file, leaving a blank js file with // extracted by mini-css-extract-plugin
.
My solution is to group your css and js in the entry section of webpack.config.js
entry: {
demo: {
import: [ path.join("server", "scripts", "demo.js"), path.join("server", "styles", "demo.css") ],
filename: "demo.js", // outputs demo.js, demo.css to your output directory
},
main: {
import: [ path.join("server", "scripts", "main.js"), path.join("server", "styles", "main.css") ],
filename: "main.js", // outputs main.js, main.css to your output directory
},
}
Also, so naming works well, use this for your plugins section:
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css"
}),
],
Adjust the bundles "demo" and "main", as well as paths accordingly.
Upvotes: 0
Reputation: 7288
There are two workarounds for your problem. For both of them, you need to change the entry
point of the Webpack configuration file. I, personally, prefer the first option.
Option 1:
Change the entry
to the following:
entry: {
demo: [
path.resolve('server', 'scripts', 'demo.js'),
path.resolve('server', 'styles', 'demo.css'),
]
}
This will generate the following outputs (based on the filename you provided for Extract
class and output
section:
Option 2:
For this option, you need to remove the CSS file from the entry
point and import it inside the JS file:
webpack.config.js
...
entry: path.resolve('server', 'scripts', 'demo.js'),
...
demo.js
import './../styles.demo.css'
//rest of your JS codes
This solution will generate the same output as Option1
Upvotes: 0
Reputation: 8102
Please remove demo_styles
from your entry point this is creating demo_styles.js
.
instead you can inject css file like this:
plugins: [
new MiniCssExtractPlugin({
filename: 'demo_styles.css',
}),
Let me know if the issue still persists, Happy to help
Upvotes: -1