Code Monkey home page Code Monkey logo

media-query-plugin's People

Contributors

dependabot[bot] avatar sassninja avatar webdevian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

media-query-plugin's Issues

Sourcemaps not being generated

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:
image

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:
image

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))?

How to use in nuxt

Hello, my project is using nuxt for server side rendering, I did not find the documentation on how to use in nuxt

Compile loop when using webpack watch

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 },
            },
          ],
        },
      }),
    ],
  },
};

Extracted files are not available in html-webpack-plugin

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",

upgrade dependencies

There are several dependencies outdated.

Not all of them are relevant for security (and thus covered by dependabot)
Nevertheless they should be upgraded.

Does not cooperate with `contenthash` in MiniCssExtractPlugin's `filename` option

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.

The issue

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

Expected result

Output like example-desktop.[12345678].css

Actual result

output files like example-desktop.[contenthash

Additional info

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.

plugin doesn't output media related files based on query. Is it because of loaders?

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

how to remove warning

[WARNING] media-query-plugin is going to drop webpack 4 support with the next major version so you should consider upgrading asap!

Extracting css without a media query

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' }
        }),
    ]

Error with webpack 5

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!!

not working when using style-loader

When using the plugin together with the style-loader it doesn't work.

There are two problems:

  1. an additional, erroneous wrapping apostrophe (causes syntax error)
  2. the extracted CSS code get appended (via 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.

Using Regular Expression for group matching throws ERROR

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.

Laravel Mix

Is it possible to use this plugin with Laravel Mix?

Extract media query from the entire bundle

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.

Webpack outputs build files that increase in size every iteration

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).

Dynamic Import and Long Term Caching

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?

'css-loader' options not being applied to extracted media query files

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.

Direct integration with mini-css-extract-plugin

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:

https://github.com/webpack-contrib/mini-css-extract-plugin/blob/b653641e7993eb28fad70c1733dc45feafea93c5/src/index.js#L200

and here:

https://github.com/webpack-contrib/mini-css-extract-plugin/blob/b653641e7993eb28fad70c1733dc45feafea93c5/src/index.js#L174

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)

One group for all chunks

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!

Perhaps dynamic import is useless when we already have media query?

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

Error when used with Stylelint

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",

Webpack [contentHash:8] issue in production

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 ?

Bootstrap Icons SCSS

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 ?

query match tolerance

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.

File-loader and screen resizing questions

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.

Not possible to extract media queries from all css files

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!

media queries extracted multiple times

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();

more meaningful support of html-webpack-plugin

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:

  • don't inject query specific files into html-webpack-plugin without modification
  • pipe through the query information (if two queries are grouped, use the 1st match)

htmlWebpackPlugin.files.extracted.css is always empty

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?

Files with same name overrides (and not creating files matching mini-css-extract-plugin)

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.

include parameter not work with RegExp

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.

How does this plugin work with when MiniCssExtractPlugin set "filename: '[name].[chunkhash].css'"

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?

DeprecationWarning: afterOptimizeChunkAssets is deprecated

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)

Missing support for Webpack 5.0 filename being a function

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.