sassninja / media-query-plugin Goto Github PK
View Code? Open in Web Editor NEWWebpack plugin for media query extraction.
License: MIT License
Webpack plugin for media query extraction.
License: MIT License
Hi,
Could you explain the difference between media-query-plugin and postcss-combine-media-query, please?
Thanks so much.
I'm currently using the media query plugin in a project with scss and a webpack confguration. I was always able to detect the source of css in the devtools via sourcemaps like this:
After installing and configuring the media query plugin, clearing the system cache and restarting filewachters, it successfully splits the output css into seperate chunks, but it doesn't ship their sourcemaps:
Here is what my webpack.config.js
looks like:
const webpack = require('webpack');
const path = require('path');
const dist_path = __dirname + '/web/dist';
const isProd = (process.env.NODE_ENV.indexOf('production') !== -1 ? true : false);
const type = process.env.NODE_TYPE;
// Plugins
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const MediaQueryPlugin = require('media-query-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const build = {
'core' : {
'entry': './web/scss/main.scss',
'output': 'core/'
},
'email' : {
'entry': './web/scss/email.scss',
'output': 'email/'
},
'email-inline' : {
'entry': './web/scss/email-inline.scss',
'output': 'email-inline/'
}
};
const extractPlugin = new MiniCssExtractPlugin({
filename: build[type].output + 'css/[name].css',
allChunks: true
});
const cleanPath = dist_path + '/' + build[type].output;
module.exports = {
entry: build[type].entry,
output: {
path: dist_path,
filename: './' + build[type].output + '/build.js',
publicPath: '/dist',
chunkLoading: false,
wasmLoading: false,
},
module: {
rules: [
{
test: /\.(scss|css)$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: !isProd
}
},
MediaQueryPlugin.loader,
{
loader: 'postcss-loader',
options: {
sourceMap: !isProd
}
},
{
loader: 'sass-loader',
options: {
sourceMap: !isProd,
sassOptions: {
indentWidth: 4,
includePaths: [path.resolve(__dirname, "./node_modules/compass-mixins/lib")]
}
}
}
]
},
{
test: /\.(jpe?g|gif|png|svg)(\?[a-z0-9=.]+)?$/,
loader: 'url-loader',
exclude: /node_modules/,
options: {
limit: 20000,
name: build[type].output + 'images/[hash]-[name].[ext]',
publicPath: '../../'
}
},
{
test: /\.(woff|woff2|eot|ttf)(\?[a-z0-9=.]+)?$/,
loader: 'url-loader',
exclude: /node_modules/,
options: {
limit: 20000,
name: build[type].output + 'fonts/[name].[ext]',
publicPath: '../../'
}
}
]
},
devServer: {
historyApiFallback: true,
noInfo: true
},
performance: {
hints: false
},
devtool: (isProd ? false : 'source-map'),
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [cleanPath]
}),
new MediaQueryPlugin({
include: [
'main'
],
queries: {
'(min-width: 480px)': 'desktop',
'(min-width: 480px) and (max-width: 640px)': 'desktop',
'(min-width: 600px)': 'desktop',
'(min-width: 641px)': 'desktop',
'(min-width: 641px) and (max-width: 767px)': 'desktop',
'(min-width: 768px)': 'desktop',
'(min-width: 768px) and (max-width: 1023px)': 'desktop',
'(min-width: 768px) and (max-width: 1439px)': 'desktop',
'(min-width: 1024px)': 'desktop',
'(min-width: 1024px) and (max-width: 1279px)': 'desktop',
'(min-width: 1280px)': 'desktop',
'(min-width: 1280px) and (max-width: 1439px)': 'desktop',
'(min-width: 1440px)': 'desktop',
'(min-width: 1440px) and (max-width: 1699px)': 'desktop',
'(min-width: 1700px)': 'desktop',
'only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2)': 'desktop',
'print': 'print',
}
}),
extractPlugin
],
watch: (type == 'core' && !isProd ? true : false),
watchOptions: {
aggregateTimeout: 500,
ignored: /node_modules/
},
stats: 'normal'
}
if (process.env.NODE_ENV === 'production') {
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
})
])
}
How can I get my sourcemaps back? Does it maybe have to do something with the loaders being ignored as stated in Issue #18 (See #18 (comment))?
Hello, my project is using nuxt for server side rendering, I did not find the documentation on how to use in nuxt
I have an issue, where the additional CSS files, keeps compiling when using the watch command, even without change. Everything works as expected in normal compile mode, and in serve mode.
It is a bit shortened, but should have all relevant plugins etc.
I have the following webpack config:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MediaQueryPlugin = require('media-query-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const resolveConfig = require('tailwindcss/resolveConfig');
const tailwind = resolveConfig(require('./tailwind.config'));
module.exports = {
devtool: process.env.NODE_ENV === 'development' ? 'inline-source-map' : false,
target: 'web',
entry: app: {
import: path.join(__dirname, 'resources/app.js'),
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
new MediaQueryPlugin({
include: [
'app',
],
queries: (() => {
const keys = Object.keys(tailwind.theme.screens);
const values = Object.values(tailwind.theme.screens);
const queries = {};
keys.forEach((key, index) => {
const value = values[index];
if (typeof value === 'string') {
queries[`(min-width: ${value})`] = key;
}
});
return queries;
})(),
}),
],
output: {
filename: '[name].js',
path: path.join(__dirname, 'src/assets'),
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
url: false,
},
},
MediaQueryPlugin.loader,
'postcss-loader',
],
},
],
},
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
format: {
comments: false,
},
},
extractComments: false,
}),
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
'default',
{
discardComments: { removeAll: true },
},
],
},
}),
],
},
};
I'm trying to access htmlWebpackPlugin.files.extracted.css
, but I get a error
ERROR in Template execution failed: TypeError: Cannot read property 'css' of undefined
It started after I updated the html-webpack-plugin
3.2.0
-> 4.2.1
"media-query-plugin": "1.3.1",
"html-webpack-plugin": "4.2.1",
"webpack": "4.43.0",
There are several dependencies outdated.
Not all of them are relevant for security (and thus covered by dependabot)
Nevertheless they should be upgraded.
Thank you for this project. It's very valuable for user experience and I appreciate that you've filled this gap. I'm surprised this technique isn't more widely sought.
In the plain-webpack example webpack.config.js, change the filename
option from this
new MiniCssExtractPlugin({
filename: '[name].css'
}),
to this
new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css'
}),
Then run npm run start
Output like example-desktop.[12345678].css
output files like example-desktop.[contenthash
Interestingly, this works
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
}),
And I'm able to set output.hashDigestLength = 8
, to get the desired hash length in the generated files. So we have a workaround that's viable for some situations, but perhaps not all.
First of all great plugin which i was looking for to reduce the file size and improve the performance of the website.
I am having issue in generating query related files. Can you help me out what is wrong in the below code'
plugins: [
new DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
'ENV_PROXY': JSON.stringify(env.proxy),
}),
new CopyWebpackPlugin({
patterns: [
{ from: resolve(projectRoot, 'assets//*'), to: resolve(projectRoot, 'dist/web-react/assets') },
{ from: resolve(projectRoot, 'locales//*'), to: resolve(projectRoot, 'dist/web-react/locales') }
]
}),
new MiniCssExtractPlugin({
filename: 'web-react/assets/css/[name].css',
chunkFilename: 'web-react/assets/css/[name].chunk.css',
ignoreOrder: true // ignores chunk order console warnings (https://www.npmjs.com/package/mini-css-extract-plugin#remove-order-warnings)
}),
new MediaQueryPlugin({
include: true,
queries: {
'(max-width: 479px)': 'mobile',
'(max-width: 839px)': 'tablet'
}
}),
//new MobileFirstMediaQueriesSplitterPlugin([600, 1024]),
new WatchIgnorePlugin({
paths: [
'cypress/**/*'
]}),
],
Thanks
[WARNING] media-query-plugin is going to drop webpack 4 support with the next major version so you should consider upgrading asap!
Hi! Thank you for building this awesome package :)
Is there a way to extract the leftover css without media queries, additionally to the media-query chunks?
.red {
color: red;
}
@media (min-width:1080px) {
.red {
color: maroon;
}
}
That would give me the latter rule as style-lg.css
, but I still want to include style.css
with the former rule only. The MiniCssExtractPlugin only gives the complete css and the media-query-chunks back.
Here's my config:
module: {
rules: [
{
test: /styles.css/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
MediaQueryPlugin.loader,
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: `generated/css/[name].[contenthash].css`,
}),
new MediaQueryPlugin({
include: true,
queries: {
'(max-width:719px)': 'sm',
'(min-width:720px) and (max-width:1079px)': 'md',
'(min-width:1080px)': 'lg' }
}),
]
Hi!!!
When i try to use this plugin with Webpack 5... error... =(
Error: Compilation.chunks was changed from Array to Set (using Array method 'sort' is not possible) at Set.set.<computed> [as sort] (/Users/CODE/node_modules/webpack/lib/util/deprecation.js:117:10) at /Users/CODE/node_modules/media-query-plugin/src/plugin.js:165:45 at /Users/CODE/node_modules/webpack/lib/Compilation.js:337:47 at Hook.eval [as callAsync] (eval at create (/Users/deploy/CODE/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:54:1) at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/Users/CODE/node_modules/tapable/lib/Hook.js:18:14) at cont (/Users/CODE/node_modules/webpack/lib/Compilation.js:1997:33) at /Users/CODE/node_modules/webpack/lib/Compilation.js:2043:9 at /Users/CODE/node_modules/neo-async/async.js:2830:7 at Object.each (/Users/CODE/node_modules/neo-async/async.js:2850:39) at Compilation.createChunkAssets (/Users/CODE/node_modules/webpack/lib/Compilation.js:3108:12) at /Users/CODE/node_modules/webpack/lib/Compilation.js:2038:13 at /Users/CODE/node_modules/webpack/lib/Compilation.js:2192:5 at /Users/CODE/node_modules/neo-async/async.js:2818:7 at done (/Users/CODE/node_modules/neo-async/async.js:3522:9) at /Users/CODE/node_modules/neo-async/async.js:2830:7 at done (/Users/CODE/node_modules/neo-async/async.js:2865:11)
Is this plugin supported into version 5?
Thx!!
When using the plugin together with the style-loader it doesn't work.
There are two problems:
ConcatSource()
) โ but it must get injected into the existing source code (right after // module
)To fix no 2 I've probably to break up the whole source code via regex and then convert it back into an OriginalSource
.
When using with the following config:
new MediaQueryPlugin({
include: true,
queries: {
'screen and (min-width: 1000px)': 'desktop'
},
groups: {
app: /^example/
}
});
modules that doesn't get matched with group RegExp throws TypeError:
(node:31262) UnhandledPromiseRejectionWarning: TypeError: group.indexOf is not a function
at /Users/david/Projects/new/app:1:48
at getGroupName (/Users/david/Projects/new/node_modules/media-query-plugin/src/postcss.js:29:52)
at callback (/Users/david/Projects/new/node_modules/media-query-plugin/src/postcss.js:42:35)
...
Seems typeof group === 'object'
guard on line 29 of src/postcss.js
should be more stricter and check if group is array. Regexps are object and when their names does not get match on previous line, pass this guard and get to group.indexOf
which obviously does not exist on regular expressions.
The extracted files have same classnames as supplied. Ideally they should be hashed.
Is it possible to use this plugin with Laravel Mix?
Hi,
I'd like your plugin! It would be amazing if I could extract from the entire bundles. Es:
// webpack.config.js
module.exports = {
context: path.resolve(__dirname, 'WebSrc'),
entry: {
page: './js/page.js',
},
[...]
module: {
rules: [
{
test: /\.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: true
}
},
MediaQueryPlugin.loader,
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')(),
],
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
[...]
]
},
optimization: {
splitChunks: {
minSize: 1,
cacheGroups: {
js: {
test: /\.js$/,
name: "commons",
chunks: "all",
minChunks: 7,
},
css: {
test: /\.s?css$/,
name: "commons",
chunks: "all",
minChunks: 7,
},
}
}
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: "dist/[name].css",
}),
new MediaQueryPlugin({
include: true,
queries: {
'(min-width: 1200px)': 'xl'
}
}),
],
};
// page.js
import "./a.scss";
import "./b.scss";
This configuration will generate page.js
and page.css
dist files. I'd like to extract media query from entry and not from components (a.scss
, b.scss
). I'd like something like page.css
, page-xl.css
and so on.
Thank you for your help.
Heya!
Really useful package, has vastly improved performance on our websites with a little PHP magic โค
I am running into an issue where the output files for the media queries increase in size every time Webpack Watch is triggered. The first pass done by Webpack works, but then further passes done with watching appear to append to the output files (even though the output filenames change).
Is this a chunk issue? It's likely something with my Webpack configuration and if that's the case do you have any advice?
Here's an approximate view of my config:
output: {
path: outputFolderPath,
filename: "[name].[hash].js",
publicPath: "/media/",
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: path.resolve(rootFolder, "/media/"),
},
},
'css-loader',
MediaQueryPlugin.loader,
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
require('postcss-import'),
require('postcss-nested'),
require('tailwindcss')(require(resourceFiles["configuration.js"])),
require('autoprefixer'),
require('cssnano')({ preset: 'default' }),
],
minimize: true,
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
}),
new MediaQueryPlugin({
include: /.+/,
queries: (function(){
var resolveTailwindConfig = require('tailwindcss/resolveConfig');
var websiteTailwindConfig = require(resourceFiles["configuration.js"])
var finalConfig = resolveTailwindConfig(websiteTailwindConfig);
var queries = Object.keys(finalConfig.theme.screens).reduce((accum, screenKey) => {
accum[`(min-width:${finalConfig.theme.screens[screenKey]})`] = screenKey;
accum[`screen (min-width:${finalConfig.theme.screens[screenKey]})`] = screenKey;
return accum;
}, {});
return queries;
})(),
groups: {
responsive: /.+/,
}
}),
//...
],
I don't have any chunk optimisations currently in place (already a speedy compilation and realtime load).
In part 3 of README you've described how to use extracted files through dynamic import but what if the name of extracted files includes a hash ( i.e. [name].[contenthash].css
generated through MiniCssExtractPlugin then Splitted using MediaQueryPlugin ) ? Is it possible to dynamic import generated files that have a hash in them via this plugin?
Hi,
I am trying to incorporate the media-query-plugin
into our Webpack build but it is not working as expected, and I'm wondering if there something obvious that I am doing wrong or missing, or if it's a bug?
The problem is with css-loader
options not being applied to media query files. Specifically I use the modules
option and set localIdentname
in css-loader
. This works correctly for rules in the non-media query bundle:
.Button__default__1OhNF {
...
}
but rules in the extracted media query bundles are not getting modified:
@media screen and (min-width: 960px) {
.container--slim > div {
...
}
This is what my config looks like:
plugins: [
...
new MediaQueryPlugin({
include: true,
queries: {
'screen and (min-width: 640px)': 'medium',
'screen and (min-width: 960px)': 'large',
'screen and (min-width: 1280px)': 'x-large',
},
groups: {
bundle: /.*/
},
}),
new MiniCssExtractWebpackPlugin(
{
filename: '[name].[contenthash].css',
}
),
],
module: {
rules: [
{
test: /\.(scss|css)$/,
use: [
MiniCssExtractWebpackPlugin.loader,
{
loader: 'css-loader',
options: {
modules: {
localIdentName: isDev ? '[name]__[local]__[hash:base64:5]' : '[hash:base64:5]',
},
importLoaders: 2,
},
},
MediaQueryPlugin.loader,
'postcss-loader',
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: getBrandResources(__dirname, brandName),
},
},
],
},
],
},
Thanks.
Hey @SassNinja
it took me way to long to discover this repo.
In many projects we face the problem your plugin is trying to solve.
I had an idea which would probably cause a lot of work but should simplify the configuration and performance of your plugin.
What if the mini-css-extract-plugin
would introduce a hook here:
and here:
So you could split the files generated by mini-css-extract-plugin whenever they are generated or regenerated.
The configuration could look like the following:
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin(),
new MediaQueryPlugin()
]
};
Maybe you could also provide some defaults e.g. split print styles and all styles for viewports larger than (e.g.) 1000px ?
This would provide an awesome zero config experience and people could just add the plugin to every project without worrying about details. (at least for basic usage)
I'd like to have an option to extract all media queries into a certain group without specifying a list of chunks for it.
So if i specify in webpack config
new MediaQueryPlugin({
include: true,
queries: {
'(min-width: 1024px)': 'desktop'
},
groups: {
'app-bundle': 'ALL_CHUNKS'
}
}),
I would receive app-bundle.css and app-bundle-desktop.css after the build. I think it can be done in src/postcss.js:26 just by adding a check like:
if (group === 'ALL_CHUNKS') {
return groupName;
}
Thank you for an awesome plugin!
In this example example/webpack
๏ผwe use
import(/* webpackChunkName: 'example-desktop' */ './example-desktop.scss');
to import an example-desktop file dynamically.
But in the result file๏ผmedia-query code ๏ผ
<link rel="stylesheet" href="example2-desktop.css" media="print, screen and (max-width: 60em)"
will load css file already and automatically.
So๏ผIs examples/webpack/src/example-desktop.scss
file and javascript dynamic import necessary?
BTW๏ผwhat you're doing is wonderful๏ผ Thanks
Hi!
I try to create a setup consisting of sass
, stylelint
and media-query-plugin
, but the combination of media-query-plugin
and stylelint-webpack-plugin
produces an error. If I remove one of the 2 plugins everything works fine. But together following error occurs:
UnhandledPromiseRejectionWarning: TypeError: Cannot read property โsyntaxโ of undefined
at Root.toString (src/frontend-core/node_modules/postcss-syntax/patch-postcss.js:38:67)
at addToStore (src/frontend-core/node_modules/media-query-plugin/src/postcss.js:14:51)
at /src/frontend-core/node_modules/media-query-plugin/src/postcss.js:59:17
I can avoid this error if I remove certain MediaQueryPlugin
queries. It works, for example, with a (min-width: 1200px)
query (there are only very few of those in my sass code base). But I could not pinpoint which sass code leads to the error.
My Webpack config looks like this:
{
plugins: [
new MediaQueryPlugin({
filename: `styles-nomobile.css`,
include: true,
queries: {
'(min-width: 480px)': 'desktop',
'(min-width: 600px)': 'desktop',
'(min-width: 768px)': 'desktop',
}
}),
new MiniCssExtractPlugin({
filename: `styles.css`,
}),
new StyleLintPlugin({
files: pathsConfig.bundleRoot + '/**/*.scss',
lintDirtyModulesOnly: env === 'dev' && process.argv.indexOf('--watch') >= 0
})
],
module: {
rules: [
{
test: /\.s?[ac]ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {url: false, sourceMap: true}
},
MediaQueryPlugin.loader,
{
loader: 'sass-loader',
options: {sourceMap: true}
}
]
}
]
},
...
}
The used package versions:
"node-sass": "4.14.1",
"media-query-plugin": "^1.1.0",
"mini-css-extract-plugin": "0.11.2",
"postcss": "^8.0.9",
"stylelint": "13.7.1",
"stylelint-config-standard": "20.0.0",
"stylelint-no-unsupported-browser-features": "^4.0.0",
"stylelint-webpack-plugin": "2.1.0",
Hello @SassNinja,
I have been facing some issues going from dev to prod in my project.
The files are named with a contenthash variable at the end.
However, without specific configuration I end up with a filename like : /public/path/myfile.[contenthash:8].css
The contenthash is not capture and so I configured MiniCssExtractPluging in my webpack as:
Encore.addPlugin(new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
}))
However, this is still not working because the length of the contenthash is not 8 chars. Moreover, I would have expected same hash as the main entry it comes from, but this is not the case.
For instance, I have a "app" entry in my webpack configuration and files got a hash, the one from media-query-plugin another and they are not referenced in the entrypoint.json so I cannot use them. Any hint or solution maybe ?
Hello, I have in my project a bootstrap-icons.scss
that is not properly generated when using media-query-plugin.
Module build failed: Module not found:
"./assets/styles/base.scss.webpack[javascript/auto]!=!./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].oneOf[1].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].oneOf[1].use[2]!./node_modules/resolve-url-loader/index.js??ruleSet[1].rules[4].oneOf[1].use[3]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].oneOf[1].use[4]!./node_modules/media-query-plugin/src/loader.js!./node_modules/postcss-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./assets/styles/base.scss" contains a reference to the file "./fonts/bootstrap-icons.woff2?24e3eb84d0bcaf83d77f904c78ac1f47".
This file can not be found, please check it for typos or update it if the file got moved.
"./assets/styles/base.scss.webpack[javascript/auto]!=!./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].oneOf[1].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].oneOf[1].use[2]!./node_modules/resolve-url-loader/index.js??ruleSet[1].rules[4].oneOf[1].use[3]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].oneOf[1].use[4]!./node_modules/media-query-plugin/src/loader.js!./node_modules/postcss-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./assets/styles/base.scss" contains a reference to the file "./fonts/bootstrap-icons.woff?24e3eb84d0bcaf83d77f904c78ac1f47".
This file can not be found, please check it for typos or update it if the file got moved.
This file exists "./fonts/bootstrap-icons.woff", but the issue comes from the hash in tail of the filename. Is there any reason why this is only showing up media-query-plugin
on ? Maybe some specificities in the loaders ?
Currently the queries match is very strict what might result in unintended results.
This occurs in particular when using some compiler such as sass.
Example:
// webpack.config.js
queries: {
'(min-width:1000px)': 'desktop'
}
// style.scss
.foo { color: red }
@media (min-width:1000px) {
.foo { color: green }
}
The expected result would be a style.css
and a style-desktop.css
with the extracted CSS.
But that's what you get:
// style.css
.foo {
color: red;
}
@media (min-width: 1000px) {
.foo {
color: green;
}
}
That's not what you want, is it?
The reason is the query match is very strict and since the sass compiler has changed the code (added a whitespace) the query doesn't match anymore because '(min-width:1000px)' !== '(min-width: 1000px)'
To fix this the comparison should be more tolerant (e.g. by normalizing the query before comparing) so that the example above works.
Hi,
I've been trying this plugin, and have the following questions:
1. Using MediaQueryPlugin with file-loader:
I'm using file-loader to resolve references to images in my CSS files, so that they can be emitted to the output directory after Webpack runs.
Before using media query plugin, Webpack would recognize the references to images inside media queries in the main.css file, and place the images in the public directory correctly.
After adding media query plugin to my webpack config, Webpack separated media queries into its own CSS files correctly, but the references to images inside those media queries don't seem to be recognized anymore, so the image output folder is not created in my "/public" directory.
I managed to solve this by importing images using:
require.context("./img/", true, /\.(png|svg|jpg|gif)$/);
But would have expected them to be resolved automatically.
2. Screen resizing:
The behavior I was looking for is that the page would request a different CSS when reaching a new breakpoint.
This can be done by using something like:
<link rel="stylesheet" media="(max-width:480px)" href="main-mobile.css">
In that case, the file will be loaded in a non-blocking way, and with lower priority, when the screen has a different size, but be available when the screen changes so it can be used.
Following the instructions for using extracted files, the page does load the right CSS at page load time, according to the viewport of the requesting device, but doesn't request a different stylesheet dynamically when the viewport changes.
Wondering if there's any better way of doing this, without using the link rel tag shared before.
Here's the content of webpack.config.js:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const MediaQueryPlugin = require('media-query-plugin');
module.exports = {
mode: 'production',
entry: {
main: "./src"
},
output: {
path: path.resolve(__dirname, "public"),
filename: "[name].bundle.js",
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/'
}
}]
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", MediaQueryPlugin.loader, "postcss-loader"]
}
]
},
plugins: [
new HtmlWebpackPlugin({ template: "./src/index.html" }),
new MediaQueryPlugin({ include: ['style'], queries: { '(max-width: 480px)': 'mobile', '(min-width: 481px) and (max-width: 1024px)': 'tablet', '(min-width: 1025px)': 'desktop' }, groups: { main: ['style'] } }),
new MiniCssExtractPlugin({ filename: "[name].css" })
]
}
And this is the main css file:
@font-face {
font-family: 'Dancing Script';
font-style: normal;
font-weight: 400;
font-display: swap;
src: local('Dancing Script Regular'), local('DancingScript-Regular'), url(https://fonts.gstatic.com/s/dancingscript/v10/If2RXTr6YS-zF4S-kcSWSVi_szLgiuEHiC4W.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
html, body {
min-height: 100%;
}
body {
background-position: center center;
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
}
header {
text-align: center;
}
h1 {
font-family: 'Dancing Script', cursive;
color: #fff;
font-size: 60px;
padding-top: 20px;
margin-top: 0;
padding-top: 20px;
}
h3 {
font-family: 'Dancing Script', cursive;
font-size: 40px;
}
.btn-custom {
text-transform: uppercase;
color: #fff;
background-color: #3498DB;
border: 0;
padding: 14px 20px;
margin: 0;
font-size: 16px;
font-weight: 500;
letter-spacing: 0.5px;
border-radius: 0;
transition: all 0.5s;
margin-top: 20px;
}
@media (max-width: 480px) {
body {
background-image: url(./img/background-mobile.jpg);
}
}
@media (min-width: 481px) and (max-width: 1024px) {
body {
background-image: url(./img/background-tablet.jpg);
}
}
@media (min-width: 1025px) {
body {
background-image: url(./img/background-desktop.jpg);
}
}
Thanks in advance.
Hi. Thanks for this really handy plugin.
Afaiu currently it's not possible to extract media queries from all the files in the project, i.e. main bundle which is for instance myapp.css
. It would be really nice if I ignore include
option all the css files are gathered. Is it possible with current implementation of this plugin? mike-diamond/media-query-splitting-plugin
does support this yet since it has some limitations it doesn't fit for my needs.
Thanks!
First, props for this plugin!
It's time we use separate files for media queries to prevent unnecessary render blocking.
I'm using the symfony/webpack-encore bundle for an easy webpack configuration.
When I use yarn run encore dev --watch
to automatically recompile the assets, after the first changes and recompiling I can see that the media queries are extracted multiple times.
If I quit the watch task and run it again the media queries seem extracted correctly again.
// webpack.config.js
const Encore = require('@symfony/webpack-encore');
const MediaQueryPlugin = require('media-query-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
Encore
// empty the outputPath dir before each build
.cleanupOutputBeforeBuild()
// show OS notifications when builds finish/fail
.enableBuildNotifications()
// the project directory where all compiled assets will be stored
.setOutputPath('web/build/')
// the public path used by the web server to access the previous directory
.setPublicPath('/build')
// will create web/build/app.js and web/build/app.css
.addEntry('app', './web_src/assets/js/app.js')
// allow sass/scss files to be processed
// .enableSassLoader()
.enablePostCssLoader()
// allow legacy applications to use $/jQuery as a global variable
.autoProvidejQuery()
.enableSourceMaps(!Encore.isProduction())
// enable react
.enableReactPreset()
.configureBabel(function(babelConfig) {
babelConfig.plugins = [
'transform-class-properties',
'transform-object-rest-spread'
];
})
.addLoader({
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
MediaQueryPlugin.loader,
'postcss-loader',
'sass-loader'
]
})
.addPlugin(
new MediaQueryPlugin({
include: ['app'],
queries: {
// commented media queries are not worth it (yet)
'(max-width: 575.98px)': 'xs-down',
'(min-width: 576px)': 'sm-up',
// '(max-width: 767.98px)': 'sm-down',
'(min-width: 768px)': 'md-up',
// '(max-width: 991.98px)': 'md-down',
'(min-width: 992px)': 'lg-up',
// '(max-width: 1199.98px)': 'lg-down',
'(min-width: 1200px)': 'xl-up',
// '(min-width: 576px) and (max-width: 767.98px)': 'sm-only',
// 'screen and (prefers-reduced-motion: reduce)': 'prm',
print: 'print'
}
})
);
module.exports = Encore.getWebpackConfig();
At the moment this plugins supports html-webpack-plugin by providing the extracted files (e.g. example-desktop.css
) to it.
But this use case makes the media-query-plugin somehow unnecessary because it doesn't make sense to first extract all media queries and then initially load them anyway.
The only meaningful use case would be to provide the additional files incl. query data so the you get automatically something as
<link rel="stylesheet" href="example-desktop.css" media="(min-width: 60em)">
This way the user still needs to download the unnecessary file but it doesn't get applied to the browser's CSS object. So we've got at least a meaningful use case (most of the time dynamic import is recommended way to load the extracted CSS).
Thus TODO is:
Hey there,
I am figuring out how to use your plugin. But I cannot get it working. It is not extracting anything at all. I finally decided to try to inject the css links manually in the template with a forEach on htmlWebpackPlugin.files.extracted.css. And the surprise, htmlWebpackPlugin.files.extracted.css is not defined at all. I am not exactly sure what is going wrong, so now I finally reach out here for help :)
So first of all my environment:
package.json
{
"@babel/core": "^7.4.3",
"@babel/plugin-proposal-class-properties": "^7.4.0",
"@babel/plugin-proposal-decorators": "^7.4.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.4.3",
"@babel/register": "^7.4.0",
"aurelia-cli": "^1.0.0-beta.15",
"aurelia-loader-nodejs": "^1.0.1",
"aurelia-pal-nodejs": "^1.2.0",
"aurelia-testing": "^1.0.0",
"aurelia-tools": "^2.0.0",
"aurelia-webpack-plugin": "^3.0.0",
"autoprefixer": "^9.5.0",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-loader": "^8.0.5",
"babel-preset-es2015": "^6.24.1",
"copy-webpack-plugin": "^4.5.2",
"critters-webpack-plugin": "^2.3.0",
"css-loader": "^1.0.0",
"cssnano": "^4.1.10",
"del": "^3.0.0",
"duplicate-package-checker-webpack-plugin": "^3.0.0",
"eslint": "^5.16.0",
"expose-loader": "^0.7.5",
"file-loader": "^2.0.0",
"gulp": "^4.0.0",
"gulp-rename": "^1.4.0",
"hammerjs": "^2.0.8",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"istanbul-instrumenter-loader": "^3.0.1",
"jest": "^23.6.0",
"jest-cli": "^23.6.0",
"jquery": "^3.3.1",
"json-loader": "^0.5.7",
"link-media-html-webpack-plugin": "^2.0.0",
"media-query-plugin": "^1.3.0",
"media-query-splitting-plugin": "^1.1.13",
"mini-css-extract-plugin": "^0.4.3",
"minimatch": "^3.0.4",
"moment": "^2.24.0",
"nps": "^5.9.5",
"nps-utils": "^1.7.0",
"opn": "^5.5.0",
"plugin-error": "^1.0.1",
"postcss-color-function": "^4.1.0",
"postcss-font-magician": "^2.2.1",
"postcss-loader": "latest",
"request": "^2.88.0",
"request-promise": "^4.2.4",
"slick-carousel": "^1.8.1",
"style-loader": "^0.23.1",
"through2": "^2.0.3",
"url-loader": "^1.1.1",
"vinyl-fs": "^3.0.3",
"webpack": "^4.29.6",
"webpack-bundle-analyzer": "^3.1.0",
"webpack-cli": "^3.3.0",
"webpack-dev-server": "^3.2.1"
}
from the config
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Critters = require('critters-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const MediaQueryPlugin = require('media-query-plugin');
const DuplicatePackageCheckerPlugin = require('duplicate-package-checker-webpack-plugin');
const project = require('./aurelia_project/aurelia.json');
const {
AureliaPlugin,
ModuleDependenciesPlugin
} = require('aurelia-webpack-plugin');
const { ProvidePlugin } = require('webpack');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
// config helpers:
const ensureArray = config =>
(config && (Array.isArray(config) ? config : [config])) || [];
const when = (condition, config, negativeConfig) =>
condition ? ensureArray(config) : ensureArray(negativeConfig);
// primary config:
const title = 'Something';
const outDir = path.resolve(__dirname, project.platform.output);
const srcDir = path.resolve(__dirname, 'src');
const nodeModulesDir = path.resolve(__dirname, 'node_modules');
const baseUrl = '/';
const cssRules = [
{ loader: 'css-loader' },
MediaQueryPlugin.loader,
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({ browsers: ['last 2 versions'] }),
require('postcss-color-function'),
require('cssnano')({ preset: 'default' })
]
}
}
]
module.exports = ({
production,
server,
extractCss,
coverage,
analyze,
karma
} = {}) => ({
resolve: {
extensions: ['.js'],
modules: [srcDir, nodeModulesDir],
// Enforce single aurelia-binding, to avoid v1/v2 duplication due to
// out-of-date dependencies on 3rd party aurelia plugins
alias: {
'aurelia-binding': path.resolve(__dirname, 'node_modules/aurelia-binding')
}
},
entry: {
app: ['aurelia-bootstrapper']
},
mode: production ? 'production' : 'development',
output: {
path: outDir,
publicPath: baseUrl,
filename: production
? '[name].[chunkhash].bundle.js'
: '[name].[hash].bundle.js',
sourceMapFilename: production
? '[name].[chunkhash].bundle.map'
: '[name].[hash].bundle.map',
chunkFilename: production
? '[name].[chunkhash].chunk.js'
: '[name].[hash].chunk.js'
},
optimization: {
runtimeChunk: true, // separates the runtime chunk, required for long term cacheability
// moduleIds is the replacement for HashedModuleIdsPlugin and NamedModulesPlugin deprecated in https://github.com/webpack/webpack/releases/tag/v4.16.0
// changes module id's to use hashes be based on the relative path of the module, required for long term cacheability
moduleIds: 'hashed',
// Use splitChunks to breakdown the App/Aurelia bundle down into smaller chunks
// https://webpack.js.org/plugins/split-chunks-plugin/
splitChunks: {
hidePathInfo: true, // prevents the path from being used in the filename when using maxSize
chunks: 'initial',
// sizes are compared against source before minification
maxInitialRequests: Infinity, // Default is 3, make this unlimited if using HTTP/2
maxAsyncRequests: Infinity, // Default is 5, make this unlimited if using HTTP/2
minSize: 10000, // chunk is only created if it would be bigger than minSize, adjust as required
maxSize: 40000, // splits chunks if bigger than 40k, adjust as required (maxSize added in webpack v4.15)
cacheGroups: {
default: false, // Disable the built-in groups default & vendors (vendors is redefined below)
// You can insert additional cacheGroup entries here if you want to split out specific modules
// This is required in order to split out vendor css from the app css when using --extractCss
// For example to separate font-awesome and bootstrap:
// fontawesome: { // separates font-awesome css from the app css (font-awesome is only css/fonts)
// name: 'vendor.font-awesome',
// test: /[\\/]node_modules[\\/]font-awesome[\\/]/,
// priority: 100,
// enforce: true
// },
// bootstrap: { // separates bootstrap js from vendors and also bootstrap css from app css
// name: 'vendor.font-awesome',
// test: /[\\/]node_modules[\\/]bootstrap[\\/]/,
// priority: 90,
// enforce: true
// },
// This is the HTTP/2 optimised cacheGroup configuration
// generic 'initial/sync' vendor node module splits: separates out larger modules
vendorSplit: {
// each node module as separate chunk file if module is bigger than minSize
test: /[\\/]node_modules[\\/]/,
name(module) {
// Extract the name of the package from the path segment after node_modules
const packageName = module.context.match(
/[\\/]node_modules[\\/](.*?)([\\/]|$)/
)[1];
return `vendor.${packageName.replace('@', '')}`;
},
priority: 20
},
vendors: {
// picks up everything else being used from node_modules that is less than minSize
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 19,
enforce: true // create chunk regardless of the size of the chunk
},
// generic 'async' vendor node module splits: separates out larger modules
vendorAsyncSplit: {
// vendor async chunks, create each asynchronously used node module as separate chunk file if module is bigger than minSize
test: /[\\/]node_modules[\\/]/,
name(module) {
// Extract the name of the package from the path segment after node_modules
const packageName = module.context.match(
/[\\/]node_modules[\\/](.*?)([\\/]|$)/
)[1];
return `vendor.async.${packageName.replace('@', '')}`;
},
chunks: 'async',
priority: 10,
reuseExistingChunk: true,
minSize: 5000 // only create if 5k or larger
},
vendorsAsync: {
// vendors async chunk, remaining asynchronously used node modules as single chunk file
test: /[\\/]node_modules[\\/]/,
name: 'vendors.async',
chunks: 'async',
priority: 9,
reuseExistingChunk: true,
enforce: true // create chunk regardless of the size of the chunk
},
// generic 'async' common module splits: separates out larger modules
commonAsync: {
// common async chunks, each asynchronously used module a separate chunk file if module is bigger than minSize
name(module) {
// Extract the name of the module from last path component. 'src/modulename/' results in 'modulename'
const moduleName = module.context.match(/[^\\/]+(?=\/$|$)/)[0];
return `common.async.${moduleName.replace('@', '')}`;
},
minChunks: 2, // Minimum number of chunks that must share a module before splitting
chunks: 'async',
priority: 1,
reuseExistingChunk: true,
minSize: 5000 // only create if 5k or larger
},
commonsAsync: {
// commons async chunk, remaining asynchronously used modules as single chunk file
name: 'commons.async',
minChunks: 2, // Minimum number of chunks that must share a module before splitting
chunks: 'async',
priority: 0,
reuseExistingChunk: true,
enforce: true // create chunk regardless of the size of the chunk
}
}
}
},
performance: { hints: false },
devServer: {
contentBase: outDir,
// serve index.html for all 404 (required for push-state)
historyApiFallback: true
},
devtool: production ? 'nosources-source-map' : 'cheap-module-eval-source-map',
module: {
rules: [
// CSS required in JS/TS files should use the style-loader that auto-injects it into the website
// only when the issuer is a .js/.ts file, so the loaders are not applied inside html templates
{
test: /\.css$/i,
issuer: [{ not: [{ test: /\.html$/i }] }],
use: extractCss
? [
{
loader: MiniCssExtractPlugin.loader
},
...cssRules
]
: ['style-loader', ...cssRules]
},
{
test: /\.css$/i,
issuer: [{ test: /\.html$/i }],
// CSS required in templates cannot be extracted safely
// because Aurelia would try to require it again in runtime
use: cssRules
},
{ test: /\.html$/i, loader: 'html-loader' },
{
test: /\.js$/i,
loader: 'babel-loader',
exclude: nodeModulesDir,
options: coverage ? { sourceMap: 'inline', plugins: ['istanbul'] } : {}
},
// use Bluebird as the global Promise implementation:
{
test: /[\/\\]node_modules[\/\\]bluebird[\/\\].+\.js$/,
loader: 'expose-loader?Promise'
},
// embed small images and fonts as Data Urls and larger ones as files:
{
test: /\.(png|gif|jpg|cur)$/i,
loader: 'url-loader',
options: { limit: 8192 }
},
{
test: /\.(eot|otf|ttf|woff|woff2)$/,
loader: 'file-loader?name=fonts/[name].[ext]'
},
{
test: /\.(svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/i,
loader: 'file-loader'
}
]
},
plugins: [
...when(!karma, new DuplicatePackageCheckerPlugin()),
new AureliaPlugin(),
new ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Hammer: 'hammerjs'
}),
new ProvidePlugin({
Promise: 'bluebird'
}),
new ModuleDependenciesPlugin({
'aurelia-testing': ['./compile-spy', './view-spy']
}),
new HtmlWebpackPlugin({
template: 'index.ejs',
minify: production
? {
removeComments: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
collapseBooleanAttributes: true,
removeAttributeQuotes: true,
minifyCSS: true,
minifyJS: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
ignoreCustomFragments: [/\${.*?}/g]
}
: undefined,
metadata: {
// available in index.ejs //
title,
server,
baseUrl
}
}),
// ref: https://webpack.js.org/plugins/mini-css-extract-plugin/
...when(extractCss, [
new MiniCssExtractPlugin({
// updated to match the naming conventions for the js files
filename: production
? 'css/[name].[contenthash].bundle.css'
: 'css/[name].[hash].bundle.css',
chunkFilename: production
? 'css/[name].[contenthash].chunk.css'
: 'css/[name].[hash].chunk.css'
})
]),
...when(
production || server,
new CopyWebpackPlugin([{ from: 'static', to: outDir, ignore: ['.*'] }])
), // ignore dot (hidden) files
new MediaQueryPlugin({
include: true,
queries: {
'only screen and (min-width: 1200px)': 'desktop',
'only screen and (min-width: 992px)': 'desktop',
'only screen and (max-width: 767px)': 'mobile'
}
}),
//new Critters({
// preload: 'js'
//}),
...when(analyze, new BundleAnalyzerPlugin())
]
});
So actually this plugin doesn't seem to do anything at all currently. Maybe it is incompatible?
Aditionally I have a doubt, that this plugin can actually work with a plugin I intend to use: https://github.com/GoogleChromeLabs/critters any thoughts to that?
I've got an application which has multiple entry points... the application has this structure
src
|- home
| |- index.scss
| |- index.js
|- info
| |- index.scss
| |- index.js
However, when using the plugin, because multiple files have index
as the [name]
, it only spits out files as index-tablet.css
and index-desktop.css
.
Also, it appears the naming doesn't align with mini-css-extract-plugin
which uses the entry point name. I'm using fast-sass-loader instead of sass-loader but pretty much following the same setup as the readme.md. For example, if this was my webpack.config.js file (slimmed down... each js file adds the import
to the scss file):
module.exports = {
entry: {
home: 'src/home/index.js',
info: 'src/info/index.js',
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[chunkhash].css',
})
]
}
MiniCssExtractPlugin would output the following:
home.126a82893132ed13751e.css
home.126a82893132ed13751e.js
info.3fa7ef8e382a920a42bc.css
info.3fa7ef8e382a920a42bc.js
I would of expected this plugin to then create:
home-tablet.[chunkhash].css
home-desktop.[chunkhash].css
info-tablet.[chunkhash].css
info-desktop.[chunkhash].css
But instead it only outputs:
index-tablet.[chunkhash].css
index-desktop.[chunkhash].css
Assistance would be greatly appreciated.
Hi.
I have nodejs v11.12.0, npm 6.9.0 and webpack v4.29.6
When i set RegExp to parameter include, i see an errors.
I watch src of Loader, and find this code
// check if current file should be affected if (typeof options.include === 'object' && options.include.indexOf(options.basename) > -1) { isIncluded = true; } else if (options.include instanceof RegExp && options.basename.match(options.include)) { isIncluded = true; } else if (options.include === true) { isIncluded = true; }
If inside include RegExp, typeof return 'object' and options.include.indexOf(options.basename)
gives an error.
OS: macOS
Node.js: 10.10.0
Webpack.js: 4.17.2
In webpack.common.js
i set "HtmlWebpackPlugin"
new HtmlWebpackPlugin({
template: 'src/index.html',
title: '<titleName is private>',
inject: false,
hash: true
})
in webpack.prod.js
i set "MiniCssExtractPlugin" and "MediaQueryPlugin"
{
test: /\.(css|less)$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
MediaQueryPlugin.loader,
'less-loader'
]
}
new MiniCssExtractPlugin({
filename: '[name].[chunkhash].css',
chunkFilename: '[id].[chunkhash].css'
}),
new MediaQueryPlugin({
queries: {
'only screen and (min-width : 1224px)': 'des',
'only screen and (min-width : 1824px)': 'des'
}
}),
When I test <%= htmlWebpackPlugin.files.css %>
in my template "index.html", the output is:
1.f4287f359b9e6948080b.css?3533f6c79b197d7a89c7,main.4cfc85247524759bf20d.css?3533f6c79b197d7a89c7
but the <%= htmlWebpackPlugin.files.extracted.css %>
is a blank line.
So how could I change my settings so as to bring the plugin into use?
Not sure if it's worth opening an issue for this...
Anyway.. with Webpack 5.23.0 I get this DeprecationWarning:
(node:98245) [DEP_WEBPACK_COMPILATION_AFTER_OPTIMIZE_CHUNK_ASSETS] DeprecationWarning: afterOptimizeChunkAssets is deprecated (use Compilation.hook.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)
at /.../node_modules/media-query-plugin/src/plugin.js:243:60
at Hook.eval [as call] (eval at create (/.../node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:9:1)
at Hook.CALL_DELEGATE [as _call] (/.../node_modules/tapable/lib/Hook.js:14:14)
at Compiler.newCompilation (/.../node_modules/webpack/lib/Compiler.js:992:30)
at /.../node_modules/webpack/lib/Compiler.js:1035:29
at Hook.eval [as callAsync] (eval at create (/.../node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/.../node_modules/tapable/lib/Hook.js:18:14)
at Compiler.compile (/.../node_modules/webpack/lib/Compiler.js:1030:28)
at /.../node_modules/webpack/lib/Compiler.js:473:12
at Compiler.readRecords (/.../node_modules/webpack/lib/Compiler.js:871:11)
In WP5 you can now use functions for file output path (see https://webpack.js.org/configuration/output/#outputfilename , can also be used in MiniCssExtractPlugin and others)
The plugin currently only supports filename being a string / with a template and fails on providing a correct function that returns a string with such filename:
/node_modules/media-query-plugin/src/plugin.js:83
.replace('[name]', mediaKey)
^
TypeError: this.options.filename.replace is not a function
at /frontend/node_modules/media-query-plugin/src/plugin.js:83:42
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.