mike-diamond / media-query-splitting-plugin Goto Github PK
View Code? Open in Web Editor NEWWebpack 4 plugin for styles splitting by media query
License: MIT License
Webpack 4 plugin for styles splitting by media query
License: MIT License
Steps to reproduce:
[id].css
Result:
The pattern is ignored, chunk files follow this pattern: [id].[contenthash].css
Expected Result:
The configured pattern is used
EDIT:
created a small PR which should fix the issue: #24
Hi,
Since v2, the content hash are changing for the splitted files, which didn't happen before. So I've got :
Which is impossible to use since they are not mapped in the manifest.
I'm using the following config for mini-css-extract-plugin :
filename: '[name].[contenthash].css',
chunkFilename: '[name].[contenthash].css'
I see it's related to another issue with ids changing, is it the expected behaviour now then ? If so, can we output results in the manifest so we can have access to the files names ?
Thanks
Will be very useful to have a demo.html project and directly see the plugin and his configuration in action.
I ran into this error and followed the advice, but it didn't resolve the problem. I cloned the repo and realized that the reason was because the source
parameter is an empty string when processing my manifest
runtime chunk. This part coincides with generating my manifest.js
runtime code and the Error causes my chunk to not be created. Is there an alternative way of checking if it is using mini-css-extract-plugin
? For what it's worth, the media queries are being split out. Currently, I forked your repo and simply removed the Error, my code works fine in the meantime.
It doesn't look like there is support for using different units as px
is hard coded. Any thoughts to support this?
Either a new setting would be ideal where we can set the desired value. Allowing a setting to be set and then use that as the units of measurement throughout the plugin test strings. Something like:
new MediaQuerySplittingPlugin({
units: 'px' (default), // 'rem', etc
})
Or allowing the unit measurement to be included in the provided values and update the search strings to not append the px if inlineUnits
is set. Something like:
new MediaQuerySplittingPlugin({
media: {
mobileEnd: '30rem',
tabletEnd: '60rem',
},
inlineUnits: true,
})
Thanks for the plugin, it's been helpful so far but could be more flexible with these updates!
Does this plugin work with the webpack-stats-plugin? Once I include media-query-splitting I see the files in the output folder on disk, but they aren't showing up in the webpack stats object (so I can't transform them and then load them into the HTML file I'm generating).
edit: Here's the entire stats object I'm receiving in my transform
function:
{
assetsByChunkName: {
main: [
'index.5f4730ed.css',
'index.573e07e5.js',
'index.573e07e5.js.map'
]
}
}
{
assetsByChunkName: {
main: [
'index-legacy.5f4730ed.css',
'index-legacy.3fe56758.js',
'index-legacy.3fe56758.js.map'
]
}
}
When I use this plugin and start build my app I have minimized css files. Why?
Heya! Thanks for this plugin it is awesome. Any idea how can I keep the original file as well?
Hey Mike,
could you please push unminified source code?
I would like to add groups or range, for example if you have multiple breakpoints for mobile or when you do mobile first approach.
For example:
media: { mobileEnd: 767, tabletStart: 768, tabletEnd: 991 desktopStart: 992 }, range: true
Where range means for tablet, that any media query between tabletStart and tabletEnd would be targeted.
What do you think?
Hi,
I've been trying to use this package with external libraries (such as bootstrap) and realised that the numbers set in the config must match exactly in order to be dispatched to different css files.
So I tried modifying your package so it dispatch queries if the numbers are smaller or bigger than the ones set in config. In other words, make it work even with media queries that don't match exactly the ones set in config.
I tried it with bootstrap, seems to work, even though I've not test it thoroughly yet.
If you're interested with this idea, I can do a pull request, the commit is there.
Cheers
I believe the offending line is
media-query-splitting-plugin/dist/index.js
Line 199 in bbe8e11
Never worked on a Webpack Plugin before, but I think you need to use compiler.hooks.emit.tap(pluginName, ...
?
I'm on Webpack 4 btw.
Hi,
First of all thanks for this very useful package, got a little issue I think,
I can see some queries outputed twice in the tablet.css. example source.scss :
p {
margin: 1rem;
}
@media all and (min-width: 569px) {
p {
margin: 2rem;
}
}
desktop.css looks as expected with one directive in it but here's the result of tablet.css :
@media all and (min-width: 569px) {
p {
margin: 2rem;
}
p {
margin: 2rem;
}
}
I turned off the splitTablet option for this example. If I turn it on, tablet.css is still duplicated, but both landscape and portrait are correct.
I'm using version 1.1.17 and the boilerplate you provided on the example.
Thanks !
Can I use this plugin in Laravel mix?
is there any plan to add types ?
Unnecessary chunk generated which ultimately results in unnecessary requests. with just a simple desktop style ( i.e. @media screen and (max-width: 1025px)
) someone got all others media chunks that are empty and are not needed:
.
├── css
│ ├── main.5f62d0506ecd9afde66f.css
│ ├── main.desktop.5f62d0506ecd9afde66f.css
│ ├── main.mobile.5f62d0506ecd9afde66f.css
│ ├── main.tablet.5f62d0506ecd9afde66f.css
│ ├── main.tabletLandscape.5f62d0506ecd9afde66f.css
│ └── main.tabletPortrait.5f62d0506ecd9afde66f.css
└── index.html
while it's much better to generate just the related ones:
.
├── css
│ ├── main.5f62d0506ecd9afde66f.css
│ └── main.desktop.5f62d0506ecd9afde66f.css
└── index.html
It would be very great that someone could determine which chunks he/she wanted to generate. via config: When he does not provide a boundary that media should not be generated at all. So the following config:
new MediaQuerySplittingPlugin({
// This is default config (optional)
media: {
tabletLandscapeEnd: 1024,
},
minify: true,
units: 'px',
})
would generate only desktop
chunk and ignore others.
I found what In your plugin DOMContentLoaded
event not fired
You need use document.readyState
for check this
Example
if(document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded',afterDOMLoaded);
} else {
afterDOMLoaded();
}
function afterDOMLoaded(){
//Everything that needs to happen after the DOM has initially loaded.
}
With the latest update 1.1.14
builds in two projects fail with this error.
TypeError: MediaQuerySplittingPlugin is not a constructor
Version 1.1.13
however has no error.
$ yarn build
yarn run v1.3.2
$ webpack --production
(node:28964) DeprecationWarning: Tapable.plugin is deprecated. Use new API on .hooks
instead
Error: Cannot find module 'unquote'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:548:15)
at Function.Module._load (internal/modules/cjs/loader.js:475:25)
at Module.require (internal/modules/cjs/loader.js:598:17)
at require (D:\Yashi\Desktop\Webpack_test\node_modules\v8-compile-cache\v8-compile-cache.js:159:20)
at Object. (D:\Yashi\Desktop\Webpack_test\node_modules\svgo\plugins\prefixIds.js:17:15)
at Module._compile (D:\Yashi\Desktop\Webpack_test\node_modules\v8-compile-cache\v8-compile-cache.js:178:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
at Module.load (internal/modules/cjs/loader.js:566:32)
at tryModuleLoad (internal/modules/cjs/loader.js:506:12)
at Function.Module._load (internal/modules/cjs/loader.js:498:3)
at Module.require (internal/modules/cjs/loader.js:598:17)
at require (D:\Yashi\Desktop\Webpack_test\node_modules\v8-compile-cache\v8-compile-cache.js:159:20)
at D:\Yashi\Desktop\Webpack_test\node_modules\svgo\lib\svgo\config.js:101:40
at Array.map ()
at preparePluginsArray (D:\Yashi\Desktop\Webpack_test\node_modules\svgo\lib\svgo\config.js:66:20)
at module.exports (D:\Yashi\Desktop\Webpack_test\node_modules\svgo\lib\svgo\config.js:30:28)
at new SVGO (D:\Yashi\Desktop\Webpack_test\node_modules\svgo\lib\svgo.js:21:19)
at exports.default._postcss2.default.plugin (D:\Yashi\Desktop\Webpack_test\node_modules\postcss-svgo\dist\index.js:103:18)
at creator (D:\Yashi\Desktop\Webpack_test\node_modules\postcss\lib\postcss.js:133:35)
at initializePlugin (D:\Yashi\Desktop\Webpack_test\node_modules\cssnano\dist\index.js:31:36)
at
at process._tickCallback (internal/process/next_tick.js:182:7)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
WebPack Config File
`const path = require('path');
// Webpack Plugins
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const MediaQuerySplittingPlugin = require('media-query-splitting-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const filepath = require('./src/filepath.js');
const argv = require("yargs").argv;
var isProduction = !!argv.production;
module.exports = {
mode: 'production',
devtool: isProduction ? ' ' : 'source-map',
entry: filepath.inputPath,
output: {
path: filepath.fileP,
filename: "bundle.min.js"
},
devServer: {
contentBase: filepath.outputPath,
// writeToDisk: true,
port: 3000,
overlay: {
warnings: false,
errors: true
}
},
optimization: {
splitChunks: {
cacheGroups: {
styles: {
name: 'app',
test: /.css$/,
chunks: 'async',
// priority: 30,
enforce: true
},
vendor: {
name: 'vendors',
test: /[\/]node_modules[\/]/,
filename: "[name].min.js",
chunks: 'initial',
// priority: 30,
enforce: true
}
}
},
minimizer: [new TerserPlugin({
cache: true,
parallel: true,
extractComments: true,
terserOptions: {
mangle: true, // Note mangle.properties
is false
by default.
output: {
comments: false,
}
},
})],
},
module: {
rules: [{
test: /\.(sass|scss|css)$/,
exclude: /node_modules/,
use: [
isProduction ? MiniCssExtractPlugin.loader : "style-loader",
// "style-loader",
{
loader: "css-loader",
options: {
// minimize: true,
modules: false,
importLoaders: 1,
sourceMap: isProduction ? false : true
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: isProduction ? false : true,
ident: 'postcss'
}
},
{
loader: "sass-loader",
options: {
sourceMap: isProduction ? false : true,
includePaths: [path.resolve(__dirname, 'node_modules/compass-mixins/lib')]
}
}
]
},
{
test: /\.woff2?$|\.ttf$|\.eot$|\.svg$|\.jpg$|\.jpeg$|\.png$|\.gif$/,
use: [{
loader: 'file-loader',
}, ],
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: isProduction ? '../index.html' : 'index.html'
}),
new HtmlWebpackPlugin({
filename: isProduction ? '../about.html' : 'about.html',
template: './src/template/about.html'
}),
new HtmlWebpackPlugin({
filename: isProduction ? '../contact.html' : 'contact.html',
template: './src/template/contact.html'
}),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
// filename: 'app.[hash].css',
// chunkFilename: '[id].[hash].css',
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css',
}),
new MediaQuerySplittingPlugin({
// This is default config (optional)
media: {
mobileEnd: 568,
tabletPortraitEnd: 768,
tabletLandscapeEnd: 1024,
},
splitTablet: true,
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorPluginOptions: {
preset: ['advanced', {
comments: {
removeAll: true
}
}],
}
}),
]
}`
When making a change to a media ( for example the desktop one), this plugin changes all other media hashes too.
This is harmful to long term caching as all users ( include mobile ones ) now need to make a request to receive the new styles while nothing has changed. This should happen only to desktop users.
So when we make a change to a media, only the hash of this chunk should change and others should remain untouched as their content does not change at all.
Unfortunately does not run with webpack 5.
I am using webpack-assets-manifest
to generate a manifest.json
. Currently, the CSS is splitting out by media query, but the assets are not showing up in my manifest.json
. How do you recommend loading these assets?
** EDIT **
Also we don't have SSR enabled.
By using the following config for MiniCssExtractPlugin this plugin does not handle the loading of the chunks on module loading or windows resize anymore!
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[name].[contenthash].css',
})
While by using [id].[contenthash].css
as chunkFilename
, loading of the chunks based on size just works when their js chunks are dynamically imported but not when they are initially attached to the dom.
Hello.
With the configuration define in the example, I have this error :
D:\.....\node_modules\media-query-splitting-plugin\src\index.js:222
const chunkValue = compilation.assets[chunkName].children[0]._value
^
TypeError: Cannot read property '0' of undefined
at cssChunks.forEach (D:\.....\node_modules\media-query-splitting-plugin\src\index.js:222:82)
at Array.forEach (<anonymous>)
Can you help me ?
The code execution don't enter in "compilation.mainTemplate.hooks.requireEnsure.tap" function.
Thanks.
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.