fqborges / webpack-fix-style-only-entries Goto Github PK
View Code? Open in Web Editor NEWWebpack plugin to solve the problem of having a style only entry (css/sass/less) generating an extra js file.
License: ISC License
Webpack plugin to solve the problem of having a style only entry (css/sass/less) generating an extra js file.
License: ISC License
I am building my css bundle using webpack's require.context
.
Config
entry: {
app: './entries/application.js',
styles: './entries/styles.js'
},
styles.js
require.context('../css', false, /\.css$/);
require.context('../components', true, /\.css$/);
require.context('../pages', true, /\.css$/);
It would be super awesome to have this plugin working for js entries as well.
As of right now the plugin will only remove the corresponding .js file. When bundling using the module .mjs extension this plugin won't work.
I would gladly make a PR if you think this feature can be useful. Just let me know.
Could you please add a License?
Hello fqborges,
Thaks for your plugin, it's very helpful. But it seems something wrong in new webpack version.
I have the webpack entry
entry: {
main/modules/footer': '/xxx/src/pages/main/modules/footer/index.js',
cssAssets/open/common/footer': '/xxx/src/pages/open/common/assets/css/footer.less',
'open/modules/footer': '/xxx/src/pages/open/modules/footer/index.js',
'testnet/modules/footer': '/xxx/src/pages/testnet/modules/footer/index.js',
}
It can work as I want before when I use webapck 4.10.2.
I upgrade my webpack to version 4.43.0 recently, something is wrong. All of the file like '/footer/index.js' is removed. I just want remove the extra js file when the entry is less/css.
Any idea to fix it ?
With the following example, the registration.js
file will be created. Note that adding .css
to the middlewareScript's name will cause the correct behavior. If I have time I'll do a PR.
// Wrong behavior, doesn't remove the unwanted registration.js bundle
// Add '.css' to the middlewareScript output and it'll work correctly
const middlewareScript = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&name='
const exports = {
'index': [
'./src/client/js/index.js',
'./src/client/css/index.scss'
],
'registration': [
'./src/client/css/registration.scss'
]
}
if (process.env.NODE_ENV === 'development') {
const entryPoints = Object.keys(exports)
entryPoints.forEach((entryPoint) => {
console.log(`Add middleware to ${entryPoint}`)
exports[entryPoint].push(`${middlewareScript}${entryPoint}`) // change to "${entryPoint}.css" for correct behavior
})
}
module.exports = exports
My entry:
entry: {
"scripts/index": './source/scripts/index.js',
"styles/light": './source/styles/light.scss',
"styles/dark": './source/styles/custom/dark.scss'
},
It successfully removes the useless light.js and dark.js, but it also removes index.js!
according to the code
https://github.com/fqborges/webpack-fix-style-only-entries/blob/master/index.js#L4 it should be "extensions" instead of "default"
This is my config:
const config = {
target: "web",
entry: {
vendor: [
'js/bootstrap.js',
'js/classie.js',
'js/html5element.js',
'js/html5shiv.js',
'js/jquery.1.8.3.min.js',
'js/jquery.easing.1.3.js',
'js/jquery.isotope.js',
'js/jquery-scrolltofixed.js',
'js/respond-1.1.0.min.js',
'js/wow.js',
'css/animate.css',
'css/bootstrap.css',
'css/font-awesome.css',
'css/linecons.css',
'css/responsive.css',
],
style: ['css/style.css']
},
output: {
publicPath: "/files/",
path: path.resolve(__dirname, 'public/files'),
filename: '[name].js',
},
devServer: { // https://webpack.js.org/configuration/dev-server
port: 4444,
progress: true,
writeToDisk: true,
},
devtool: "source-map",
plugins: [
new CleanWebpackPlugin(),
new FixStyleOnlyEntriesPlugin(),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
],
module: {
rules: [
{
test: /\.html$/,
use: [
'extract-loader',
{
loader: 'html-loader',
options: {
// minimize: true,
interpolate: true,
attrs: ["img:src", "link:href"]
}
},
]
},
{
test: /\.(png|jpe?g|gif)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'images/',
name: '[name].[ext]'
}
}
]
},
{
test: /\.(woff2?|ttf|eot|svg)(\?.*?)?$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'fonts/',
name: '[name].[ext]'
}
},
]
},
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: false
}
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
}
]
}
]
},
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
},
resolveLoader: {
moduleExtensions: ['-loader']
}
};
After running webpack-dev-server, the files are generated and the css and js files for the style
entry is still there
Would it be possible to give a short overview over the changes you did, either on the Releases page:
https://github.com/fqborges/webpack-fix-style-only-entries/releases
or in a separate CHANGELOG.md?
If you have to manage large projects with dozens of dependencies it's very time-consuming to track breaking changes of all your dependencies and get an overview of new features provided in new versions without a changelog.
I understand that my request may sound a bit egoistic - asking you to investigate more time, so that I can save time - but it's not meant that way.
Your extension is very useful and I'm very thankful that you've used your time to release that to the public, so that I (and many others) can benefit from it. A changelog which allows to track changes would just be a great improvement for your users. ;-)
when running wp4 with --mode production, the error above occurs.
Seems to be magically fixed by changing
resources = modules.map(m => m.resource);
to
modules.every(m => {
if (m && m.resource) {
resources.push(m.resource);
}
})
It would be very handy to have an exclusion and/or inclusion list for parsing file strings. This would make parsing faster and more reliable and could help address issues where the script catches JS files it shouldn't.
This add-on is currently catching a JS file that it shouldn't (similar to #6), for reasons that I've yet to figure out. Although this fixes the problem in the wrong place, this would allow one to skirt past this and also to make the script only run where necessary.
I'm getting this error when running production build with with FixStyleOnlyEntriesPlugin. Should I provide some more info?
HookWebpackError: chunk.files.delete is not a function
at makeWebpackError (/home/vagrant/code/perkam/perkamkopa/node_modules/webpack/lib/HookWebpackError.js:49:9)
at /home/vagrant/code/perkam/perkamkopa/node_modules/webpack/lib/Compilation.js:1995:11
at eval (eval at create (/home/vagrant/code/perkam/perkamkopa/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:17:1)
at processTicksAndRejections (internal/process/task_queues.js:94:5)
-- inner error --
TypeError: chunk.files.delete is not a function
at Compilation.renameAsset (/home/vagrant/code/perkam/perkamkopa/node_modules/webpack/lib/Compilation.js:2957:23)
at /home/vagrant/code/perkam/perkamkopa/node_modules/webpack/lib/optimize/RealContentHashPlugin.js:284:21
at processTicksAndRejections (internal/process/task_queues.js:94:5)
at async Promise.all (index 2)
at async /home/vagrant/code/perkam/perkamkopa/node_modules/webpack/lib/optimize/RealContentHashPlugin.js:256:6
caused by plugins in Compilation.hooks.processAssets
TypeError: chunk.files.delete is not a function
at Compilation.renameAsset (/home/vagrant/code/perkam/perkamkopa/node_modules/webpack/lib/Compilation.js:2957:23)
at /home/vagrant/code/perkam/perkamkopa/node_modules/webpack/lib/optimize/RealContentHashPlugin.js:284:21
at processTicksAndRejections (internal/process/task_queues.js:94:5)
at async Promise.all (index 2)
at async /home/vagrant/code/perkam/perkamkopa/node_modules/webpack/lib/optimize/RealContentHashPlugin.js:256:6
So us indent-syntax peasants need to use the extensions
option rather than getting default treatment. We're stylesheets too damnit! π
Removing one the required js files as well only on production build.
Entry is configures as
entry: {
styles: path.resolve(commonDir, 'index.scss'),
main: path.resolve(appsDir, 'main', 'index.js'),
app1: path.resolve(appsDir, 'app1', 'index.js')
}
Removes the generated main.js
file.
This the content of index.js
file pointed by main entry.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.scss';
ReactDOM.render(<App />, document.getElementById('root'));
if (process.env.NODE_ENV === 'development') {
module.hot.accept();
}
Use report ProgressPlugin instead of printing to console.
Hi there,
I started using your webpack plugin in Vue CLI 3 (config file) a while ago.
I did not have any problems when I tried to build the project, but I noticed that I had issues with my configuration where app would be injected before vendor files and code did not work properly this way.
I had to modify my configuration file and then your plugin stopped working properly.
Old configuration: (your plugin works)
const FixStyleOnlyEntries = require('webpack-fix-style-only-entries')
module.exports = {
chainWebpack: config => {
config
.entry('vendor')
.add('./src/assets/styles/vendor.scss')
.end()
.entry('app')
.add('./src/assets/styles/app.scss')
.end()
.plugin('html')
.tap(args => {
args[0].title = process.env.VUE_APP_TITLE
return args
})
},
configureWebpack: {
plugins: [
new FixStyleOnlyEntries()
]
}
}
New configuration: (your plugin breaks)
const FixStyleOnlyEntries = require('webpack-fix-style-only-entries')
module.exports = {
chainWebpack: config => {
config.entryPoints.delete('app')
config
.entry('vendor')
.add('./src/assets/styles/vendor.scss')
.end()
.entry('app')
.add('./src/main.js')
.add('./src/assets/styles/app.scss')
.end()
.plugin('html')
.tap(args => {
args[0].title = process.env.VUE_APP_TITLE
return args
})
},
configureWebpack: {
plugins: [
new FixStyleOnlyEntries()
]
}
}
As you can see, the only thing I'm doing is removing default app
entry point and re-specifying it after vendor, along with my app.scss
file.
If I throw vue inspect
to see the actual webpack configuration, the part of entry points is looking like this:
entry: {
vendor: [
'./src/assets/styles/vendor.scss'
],
app: [
'./src/main.js',
'./src/assets/styles/app.scss'
]
}
Which is correct... However, when I run npm run build
your plugin removes the main.js
file from the build entirely.
I'd be greatful if you can fix this... I noted that you mentioned in #6 that it is solved in version 0.0.5, but it does not seem to be the case. I am using that exact version.
Hello my dear friend.
I switched from 3 to 4 versions of the webpack, and have problems reloading the page using the browsersync (as standalone package, not webpack plugin) after I make changes to the style file. I found out about this plugin here. I shot a separate video with a demonstration of my software environment.
https://cl.ly/73e1a91d894f
Please tell me why your plugin does not help me solve the problem? Maybe I did something wrong or did not understand what exactly your plugin does? I will be grateful for any help!
The plugin is not removing style only entries on subsequent compilation when running webpack in watch mode. The first run goes fine, but then it runs into issues with the _collectedModules
cache.
webpack-fix-style-only-entries/index.js
Lines 69 to 72 in 7557e38
The first run will have already pushed the style only entries into it, and it will return an empty list for the resources of the module, it will then not be considered a style only module.
Would you consider reseting _collectedModules
on every watch? Or maybe improving this cache to contain whether the module is style only (or not)?
Hi there.
This should be pretty simple to reproduce.
Assuming the default settings, and a source directory that looks like this....
.
βββ src
βΒ Β βββ css
βΒ Β βββ styles.css
βββ webpack.config.js
with an entry configuration that looks like this....
{
entry: {
styles: 'css/styles?global',
},
}
This plugin will completely miss the styles
entry, unless you explicitly set extensions
to include css?global
.
I use this pattern (and I assume others do to) when using css modules...
{ test: /\.scss$/, rules: [ { use: [MiniCssExtractPlugin.loader], }, { oneOf: [ { resourceQuery: /global/, use: [ { loader: 'css-loader', options: { url: false, importLoaders: 2, modules: false, }, }, ], }, { use: [ { loader: 'css-loader', options: { url: false, importLoaders: 2, modules: true, camelCase: 'only', localIdentName: '[name]__[local]___[hash:base64:5]', }, }, ], }, ], }, { use: [ { loader: 'postcss-loader', options: { ident: 'postcss', plugins: [ require('postcss-preset-env')(), ...(IS_PRODUCTION ? [require('cssnano')()] : []), ], }, }, { loader: 'sass-loader', options: { includePaths: ['src/css'], }, }, ], }, ], },
Thanks for your work on this!
Image of the problem: https://imgur.com/a/4XdxYQ8
Command ran: webpack --env development --watch
I'd rather not suppress alerts because I have to believe there is a better solution that can be done.
I'm seeing this error
Error: Module.indexThere was no ModuleGraph assigned to the Module for backward-compat (Use the new API)
at /app/node_modules/webpack/lib/ModuleGraph.js:814:12
at deprecated (node:internal/util:124:12)
at Function.getModuleGraphForModule (/app/node_modules/webpack/lib/ModuleGraph.js:805:18)
at NormalModule.get index [as index] (/app/node_modules/webpack/lib/Module.js:238:22)
at collectEntryResources (/app/node_modules/webpack-fix-style-only-entries/index.js:62:20)
at /app/node_modules/webpack-fix-style-only-entries/index.js:81:32
at Array.forEach (<anonymous>)
at collectEntryResources (/app/node_modules/webpack-fix-style-only-entries/index.js:75:25)
at /app/node_modules/webpack-fix-style-only-entries/index.js:35:30
at Hook.eval [as call] (eval at create (/app/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
I'm also seeing a couple of deprecation warnings in the beginning.
(node:410) [DEP_WEBPACK_CHUNK_HAS_ENTRY_MODULE] DeprecationWarning: Chunk.hasEntryModule: Use new ChunkGraph API
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:410) [DEP_WEBPACK_CHUNK_ENTRY_MODULE] DeprecationWarning: Chunk.entryModule: Use new ChunkGraph API
(node:410) [DEP_WEBPACK_MODULE_INDEX] DeprecationWarning: Module.index: Use new ModuleGraph API
Running webpack --profile --json
generates a JSON file with webpack-fix-style-only-entries output at the top
webpack-fix-style-only-entries: removing js from style only module: js/index.46b1fb85fc0ced7d86a7.js
{
"errors": [],
"warnings": [
When using an array of exports in webpack.config.js
, for example the following structure:
const first = {
entry: { ... }
}
const rest = {
entry: { ... }
}
module.exports = [first, rest]
then the caching in _entryResourcesCache
does not work as expected. module.index
is mixed up between the different objects.
One fix is to move _entryResourcesCache.length = 0;
into compilation.hooks.chunkAsset.tap
, although I expect the caching is not doing much then anymore.
Another fix is to use something else as caching key. I don't know why module.id
should sometimes be empty, but a combination of both works at least in my use-case:
function collectEntryResources(module, level = 0) {
// module.index is unique per compilation
// module.id can be null, not used here
const cacheKey = module.id ??Β module.index
if (_entryResourcesCache[cacheKey] !== undefined) {
return _entryResourcesCache[cacheKey];
}
if (typeof module.resource == "string") {
const resources = [module.resource];
_entryResourcesCache[cacheKey] = resources;
return resources;
}
const resources = [];
if (module.dependencies) {
module.dependencies.forEach(dep => {
if (dep && (dep.module || dep.originModule)) {
const nextModule = dep.module || dep.originModule;
const depResources = collectEntryResources(nextModule, level + 1);
for (let index = 0, length = depResources.length; index !== length; index++) {
resources.push(depResources[index]);
}
}
});
}
_entryResourcesCache[cacheKey] = resources;
return resources;
}
I tried this package, but it did not work for me. I created something to reproduce:
git clone -b using-MiniCssExtractPlugin https://github.com/arichter83/meteor-react-typescript-nightwatch.git
meteor npm install
meteor
In Info.tsx there is a dynamic import:
import(/* webpackChunkName: "info" */ '../../client/info.css')
This will generate a info.js and a info.css:
I20190710-18:56:58.603(2)? info.21e44ad1ca43ac862441.js 392 bytes info [emitted] info
I20190710-18:56:58.603(2)? info.css 30 bytes info [emitted] info
And the info.js will still be loaded in the client, even though I think it is obsolete:
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["info"],{
/***/ "./client/info.css":
/*!*************************!*\
!*** ./client/info.css ***!
\*************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./client/info.css?");
/***/ })
}]);
And in my webpack.config.js I use the plugin:
new FixStyleOnlyEntriesPlugin(),
Where is my mistake? Thank you for your help.
PS: I also added a StackOverflow question https://stackoverflow.com/questions/56937912/webpack-dynamic-import-scss-generates-tiny-js-files
Hello, thanks for the all hard work you have done maintaining that plugin!
A project I maintain with plenty of entry points and dependencies began to fail with the following messages being printed after the recent upgrade of the webpack-fix-style-only-entries
package:
ERROR in chunk <sensitive-data> [entry]
<sensitive-data>.ee7b68e1d49fcd616eb7.js
Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
at <sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:83:19
at Array.forEach (<anonymous>:null:null)
at collectEntryResources (<sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:79:25)
at <sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:82:30
at Array.forEach (<anonymous>:null:null)
at collectEntryResources (<sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:79:25)
at <sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:41:30
at SyncHook.eval (<anonymous>:5:1)
at Compilation.createChunkAssets (<sensitive-data>/node_modules/webpack/lib/Compilation.js:2193:28)
at <sensitive-data>/node_modules/webpack/lib/Compilation.js:1397:10
at eval (<anonymous>:9:1)
at <sensitive-data>/node_modules/html-webpack-plugin/lib/cached-child-compiler.js:237:53
at runMicrotasks (<anonymous>:null:null)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
ERROR in chunk <sensitive-data> [entry]
<sensitive-data>.fd6e52446571358b846d.js
Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
at <sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:83:19
at Array.forEach (<anonymous>:null:null)
at collectEntryResources (<sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:79:25)
at <sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:41:30
at SyncHook.eval (<anonymous>:5:1)
at Compilation.createChunkAssets (<sensitive-data>/node_modules/webpack/lib/Compilation.js:2193:28)
at <sensitive-data>/node_modules/webpack/lib/Compilation.js:1397:10
at eval (<anonymous>:9:1)
at <sensitive-data>/node_modules/html-webpack-plugin/lib/cached-child-compiler.js:237:53
at runMicrotasks (<anonymous>:null:null)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
ERROR in chunk <sensitive-data> [entry]
<sensitive-data>.e985dd23742decd8f9be.js
Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
at <sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:83:19
at Array.forEach (<anonymous>:null:null)
at collectEntryResources (<sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:79:25)
at <sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:82:30
at Array.forEach (<anonymous>:null:null)
at collectEntryResources (<sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:79:25)
at <sensitive-data>/node_modules/webpack-fix-style-only-entries/index.js:41:30
at SyncHook.eval (<anonymous>:5:1)
at Compilation.createChunkAssets (<sensitive-data>/node_modules/webpack/lib/Compilation.js:2193:28)
at <sensitive-data>/node_modules/webpack/lib/Compilation.js:1397:10
at eval (<anonymous>:9:1)
at <sensitive-data>/node_modules/html-webpack-plugin/lib/cached-child-compiler.js:237:53
at runMicrotasks (<anonymous>:null:null)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
Where the stack trace surprisingly points not to the recursive call of the collectEntryResources
function but to the line pushing multiple elements into the resources
array. And a simple replacement of that line with the following snippet completely fixes the described problem for me!
for (let index = 0, length = depResources.length; index !== length; index++) {
resources.push(depResources[index]);
}
Hi @fqborges, thank you for the great work. I was wondering if you plan to update this plugin to support Webpack 5. I'm trying to integrate it into some work project and there are some deprecation warnings.
To be more specific:
(node:12688) [DEP_WEBPACK_CHUNK_HAS_ENTRY_MODULE] DeprecationWarning: Chunk.hasEntryModule: Use new ChunkGraph API
(node:12688) [DEP_WEBPACK_CHUNK_ENTRY_MODULE] DeprecationWarning: Chunk.entryModule: Use new ChunkGraph API
(node:12688) [DEP_WEBPACK_MODULE_INDEX] DeprecationWarning: Module.index: Use new ModuleGraph API
(node:12688) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET] DeprecationWarning: chunk.files was changed from Array to Set (using Array method 'filter' is deprecated)
I can help with the upgrade if needed. Let me know and thank you in advance.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.