npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@moxy/next-webpack-oneof

v2.0.0

Published

Wraps all webpack loader rules into a single oneOf rule.

Downloads

43

Readme

next-webpack-oneof

NPM version Downloads Build Status Coverage Status Dependency status Dev Dependency status

Wraps all webpack loader rules into a single oneOf rule.

By default webpack loaders will test all files for all loaders. However, webpack does support oneOf rules, within which only the first matching rule will be used.

This plugin transfers all rules into a single oneOf rule, so no file will match more than one condition.

Installation

$ npm install --save @moxy/next-webpack-oneof

Motivation

In webpack loaders, rules to match against filenames are typically structured with the expectation that all files will try to match against all rules. With simple configurations this is not an issue, but can become problematic as complexity grows and, for example, you need different loaders for similar files.

As it is, the solution is using complex pairs of include/exclude in the rules. As the complexity of this problem grows, however, implementing these exclusion rules will get more confusing and become a hassle. To avoid this, files would have to skip all rule matching tests after their first match, to guarantee that no file matches against more than one rule by default.

Webpack implements a type of rule where that already happens, Rule.oneOf, within which only the first matching rule will be used. We want this to be the default behavior.

How

This plugin operates directly on the configuration object and wraps all rules into one single oneOf rule so that it becomes the default behavior for all rules.

This, in effect, changes how to think about loader rules as the order of rules becomes of imperative importance.

In Next.js you can use function composition to bundle together multiple operations on your webpack configuration. Given the nature of function composition, the order of execution is inverse to the nesting degree of each function call. As it concerns this plugin, because you always want this plugin to be the last function to be called, it must be the topmost function in your composition to guarantee that it has access to all loader rules in your project.

Usage

Multiple configurations can be combined together with function composition. However, as explained above, this plugin must be the topmost function call. For example:

// next.config.js
const withOneOf = require('@moxy/next-webpack-oneof');
const withCSS = require('@zeit/next-css');

module.exports = withOneOf(
    withCSS({
        cssModules: true,
    }),
);

To simplify using multiple plugins, you can also use next-compose-plugins. The examples in this document will use next-compose-plugins. As with the example above, next-webpack-oneof must be the topmost object. For example:

//next.config.js
const withPlugins = require('next-compose-plugins');
const withOneOf = require('@moxy/next-webpack-oneof');
const withCSS = require('@zeit/next-css');

module.exports = withPlugins([
    withOneOf,
    [withCSS, {
        cssModules: true,
    }],
]);

Examples

In the following examples, two loaders are used for .png files: one default loader, and one loader for specific .png files with .base64. somewhere in their filename.

Without next-webpack-oneof

Using the standard webpack implementation, you would write the rules like so:

// Without 'next-webpack-oneof'
const withPlugins = require('next-compose-plugins');

withPlugins([
    {
        webpack(config) {
            config.module.rules.push({
                // More specific rule to catch .png files that also match the `include` pattern
                test: /\.png$/,
                include: /\.base64\./,
                loader: 'some-base64-loader',
            });

            config.module.rules.push({
                // General rule to catch all .png files
                // Exclude files with '.base64.' in their filename
                test: /\.png$/,
                exclude: /\.base64\./,
                loader: 'some-loader',
            });
        },
    },
])

To avoid confusing and introducing conflicts in this configuration, you must use a combination of include and exclude to guarantee that files don't fall through to multiple loaders.

With next-webpack-oneof

Using next-webpack-oneof you can avoid having to declare complex rule exclusions, but you must be careful with the order of your rules. These examples explore how to use this plugin, and explain how the order of rules changes in different contexts.

If you're setting multiple rules in one plugin, the rules inside will output with the same order as they're written in. When you can expect this to be the case, rules with more specificity should be written before more general rules, like in this example:

// With 'next-webpack-oneof'
const withPlugins = require('next-compose-plugins');
const withOneOf = require('@moxy/next-webpack-oneof');

withPlugins([
    withOneOf,
    {
        webpack(config) {
            // More specific rule to catch .png files that also match the `include` pattern
            config.module.rules.push({
                test: /\.png$/,
                include: /\.base64\./,
                loader: 'some-base64-loader',
            });

            // General rule to catch all .png files
            config.module.rules.push({
                test: /\.png$/,
                loader: 'some-loader',
            });
        },
    },
])

However, if you're setting rules in different plugins, the bottommost plugin will execute first, with order of execution going upwards from that point. In this case, plugins with rules with more specificity should be below plugins with more general rules, like in this example:

// With 'next-webpack-oneof'
const withPlugins = require('next-compose-plugins');
const withOneOf = require('@moxy/next-webpack-oneof');

withPlugins([
    withOneOf,
    {
        webpack(config) {
            config.module.rules.push({
                // General rule to catch all .png files
                test: /\.png$/,
                loader: 'some-loader',
            });
        },
    },
    {
        webpack(config) {
            config.module.rules.push({
                // More specific rule to catch .png files that also match the `include` pattern
                test: /\.png$/,
                include: /\.base64\./,
                loader: 'some-base64-loader',
            });
    },
})

Tests

Any parameter passed to the test command is passed down to Jest.

$ npm t
$ npm t -- --watch  # To run watch mode

License

Released under the MIT License.