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

@nfq/feature-flags

v3.2.0-next.15.0.0-canary.173.1

Published

Add feature flags to babel, nextjs, SWC, react and default js code

Downloads

381

Readme

@nfq/feature-flags

Table of Contents

Description: License: MIT

This is an node module that aims for simple configuration and usage of feature flags. It is build for especially build time feature flags to enable treeshaking of unshipped features depending on the environment.

Installation:

To install the package run

npm install @nfq/feature-flags

if you are in yarn

yarn add @nfq/feature-flags

or on pnpm

pnpm install @nfq/feature-flags


Configuration:

To use feature flags there is some small configuration needed:


.eslintrc:

change it to an .eslintrc.js file because we need some functions. To prevent eslint from complaining about not existing modules there is an eslint function to set some rules for you.

The Function params used are the featureFlagImport option and the jsxImport option for the babel config to prevent eslint from firing on these pseudo imports.

example:

// can be used like this
const featureFlagsRules = require('@nfq/feature-flags/eslint/import')(['@app/features', '@nfq/feature-flags/jsx']);
// or this
const withFeatureFlags = require('@nfq/feature-flags/eslint/import');
const featureFlagsRules = withFeatureFlags(['@app/features', '@nfq/feature-flags/jsx']);

module.exports = {
    extends: [
        '@nfq'
    ],
    rules: {
        ...featureFlagsRules.rules
    }
};

next.config.js:

If you are in an nextjs environment you need some extra config to tell webpack not to cache your babel config. So here is also some little helper.

example:

const {withFeatureFlags} = require('@nfq/feature-flags/next');

module.exports = withFeatureFlags({
    // nextjs config like normal.
});

next.config.js using it with SWC:

If you are in an nextjs environment and want to use it with SWC you need some extra config to tell SWC about the Plugin and also use selected environments and feature flags you defined in the features.*.js. All options from the babel config are applicable here too.

example:

const {withFeatureFlags} = require('@nfq/feature-flags/next');
const liveFeatures = require('./features.live');
const stageFeatures = require('./features.stage');

module.exports = withFeatureFlags({
    // nextjs config like normal.
    experimental: {
        swcPlugins: [[
            '@nfq/feature-flags', {
                featureEnv: process.env.FEATURE_ENV || 'stage',
                featureFlags: {
                    live: liveFeatures,
                    stage: stageFeatures
                },
                // optional settings. These are the defaults and can be omitted.
                deprecationEnv: 'live',
                featureFlagImport: '@app/features',
                jsxImport: '@nfq/feature-flags/jsx',
                jsxWithFeature: 'WithFeature',
                jsxWithoutFeature: 'WithoutFeature'
            }
        ]]
    },
});

$${\color{red}Warning!!}$$ For the Plugin to work you have to make sure its the right Version in conjunction of the SWC core version used by your nextjs version. Here is a list for supported Versions so far:

| SWC Version | Plugin Version | | ----------- | -------------- | | 0.9*.* | 3.*.* |


webpack.config.js:

If you don't use nextjs but webpack use this instead. The param can be an Object or an function.

example:

const {withFeatureFlags} = require('@nfq/feature-flags/webpack');

module.exports = withFeatureFlags({
    // webpack config like normal.
});

package.json

To tell webpack that your project is treeshakeble you need to set an flag for it. Webpack documentation for sideEffects

example:

{
    ...
    "sideEffects": [
        "**/*.css"
    ],
    ...
}

Also to tell the plugin and module on build time in which environment it is running you have to set an FEATURE_ENV= variable these define your possible environments.

example:

{
    ...
    "scripts": {
        "build:live": "cross-env FEATURE_ENV=live next build && cross-env FEATURE_ENV=live next export",
        "build:stage": "cross-env FEATURE_ENV=stage next build && cross-env FEATURE_ENV=stage next export",
        "dev": "cross-env FEATURE_ENV=dev next dev",
    },
    ...
}

feature files:

Last but not least you need some feature files that define your flags for the environments. Filenames look always the same with features.FEATURE_ENV.js the FEATURE_ENV part is your defined environment. These files HAVE to live in your project root directory!


.babelrc:

change it to an babel.config.js file because we need some functions.

example:

const {withFeatureFlags} = require('@nfq/feature-flags/babel');

module.exports = withFeatureFlags({
    plugins: [...],
    presets: [...]
}, {
    deprecationEnv: 'live',
    featureFlagImport: '@app/features',
    jsxImport: '@nfq/feature-flags/jsx',
    jsxWithFeature: 'WithFeature',
    jsxWithoutFeature: 'WithoutFeature'
});


Configuration Settings (Babel Plugin)

| Option | type | Default | Description | | ----------------- | ------ | ---------------------- | ------------------------------------------------------------------------------- | | deprecationEnv | string | live | The feature env identifier that gets checked to show deprecations. | | featureFlagImport | string | @app/features | The import name to use if you want to import an feature flag | | jsxImport | string | @nfq/feature-flags/jsx | The import name to use if you want to import jsx helpers for react | | jsxWithFeature | string | WithFeature | The jsx component name to mark an subtree to only show with an specific feature | | jsxWithoutFeature | string | WithoutFeature | The jsx component name to mark an subtree to only show without an specific feature |



JSX props

You can import to JSX components both names defined in the babel settings section. Both have the exact same props you can use.

  • The jsxWithFeature component will only render its subtree if the feature is set to true.
  • The jsxWithoutFeature component will only render its subtree if the feature is set to false.

| Prop | type | required | Description | | --------------- | --------------------------------- | :----------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | feature | FeatureFlag or Array[FeatureFlag] | :heavy_check_mark: | Defines the feature the component should look up to determine if it should render or not. | | deprecatesOn | TimeString (YYYY-MM-DD format) | | Define an date on which the babel module will throw deprecation messages for this feature. If none is set you will get deprecation warnings if an feature is configured as true on the deprecationEnv environment. | | neverDeprecates | boolean | | If set to true the feature will never throw deprecation warnings. |



Usage:

feature.live.js (live as example FEATURE_ENV):

module.exports = {COOL_FEATURE: false};

feature.stage.js (stage as example FEATURE_ENV):

module.exports = {COOL_FEATURE: true};

Plain js Examples:

import {COOL_FEATURE} from '@app/features';

const oldFunction = () => {
    /* ... */
}

const newShinyFunction = () => {
    /* ... */
}

const featureOrNot = () => {
    if (COOL_FEATURE) {
        newShinyFunction();
    } else {
        oldFunction();
    }
}
import {COOL_FEATURE} from '@app/features';

const featureOrNot = () => {
    /* ... */
    (COOL_FEATURE) && console.log('OnlyNew')
    /* ... */
}

React Examples:

import {Component} from 'react';

import {COOL_FEATURE} from '@app/features';
import {WithFeature, WithoutFeature} from '@nfq/feature-flags/jsx';
import Live from 'Components/Live'; // gets eliminated on stage environment because feature is true.
import Stage from 'Components/Stage'; // gets eliminated on Live environment because feature is true.

export default class Test extends Component {
    render() {
        return (
            <div>
                <WithFeature feature={COOL_FEATURE}>
                    <p>This is only rendered and in the final bundle if the feature is active</p>
                    <Stage />
                </WithFeature>
                <WithoutFeature feature={COOL_FEATURE}>
                    <p>This is only rendered and in the final bundle if the feature is inactive</p>
                    <Live />
                </WithoutFeature>
            </div>
        )
    }
}

deprecateOn:

import {Component} from 'react';

import {COOL_FEATURE} from '@app/features';
import {WithFeature} from '@nfq/feature-flags/jsx';

export default class Test extends Component {
    render() {
        return (
            <div>
                <WithFeature deprecatesOn="2021-07-14" feature={COOL_FEATURE}>
                    <p>Sends an deprecation warning on build time if date is greater then deprecateOn</p>
                </WithFeature>
            </div>
        )
    }
}


Contributions:

.NFQ | Christoph Kruppe



License:

The licence used is: MIT Click on licence badge for licence details: License: MIT



Questions:

If you have any furter questions please contact the following email address: email: [email protected]