Skip to content

Commit 758ff0d

Browse files
mrleblanc101Sébastien LeBlanc
andauthored
Add build-in yn support (#47)
* [FEATURE] Add yn support * [FIX] Transpile for browser * [FIX] Improve docs * [FIX] Handle queryString: true * [FEATURE] Use a renderless component (transparent wrapper) Co-authored-by: Sébastien LeBlanc <sebastien.leblanc@libeo.com>
1 parent f5bbdee commit 758ff0d

File tree

6 files changed

+46
-25
lines changed

6 files changed

+46
-25
lines changed

Readme.md

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,16 @@
3131

3232
## Usage
3333

34-
### 1. Add module to nuxt.config.js along with the feature toggle options.
34+
### 1. Install the plugin
35+
36+
```sh
37+
npm install nuxt-feature-toggle
38+
# or
39+
yarn add nuxt-feature-toggle
40+
```
41+
42+
43+
### 2. Add module to nuxt.config.js along with the feature toggle options.
3544

3645
The toggles can be defined as a function or just as an object.
3746

@@ -72,8 +81,8 @@ module.exports = {
7281
```
7382

7483
## RuntimeConfig support
75-
If using Nuxt >= 2.13, you can use the new `publicRuntimeConfig` setting in `nuxt.config.js` to **configure
76-
feature toggles on-the-fly without having to rebuild** (only need to restart Nuxt using `nuxt start`).
84+
If using Nuxt >= 2.13, you can use the new `publicRuntimeConfig` setting in `nuxt.config.js` to **configure
85+
feature toggles on-the-fly without having to rebuild** (only need to restart Nuxt using `nuxt start`).
7786

7887
```javascript
7988
module.exports = {
@@ -87,24 +96,23 @@ module.exports = {
8796
}
8897
}
8998
```
90-
Note 1: `FEATURE_ENABLE_SOME_PREVIEW_FEATURE` is an arbitrary name, the package doesn't depend on it.
91-
You can use "Feature Flag" names eg. `FF_PREVIEW_FEATURE` or whatever suits you.
99+
> Note 1: `FEATURE_ENABLE_SOME_PREVIEW_FEATURE` is an arbitrary name, the package doesn't depend on it.
100+
You can use "Feature Flag" names eg. `FF_PREVIEW_FEATURE` or whatever suits you.
92101

93-
Note 2: If you want to use `0/1` or `"true/false"` strings to enable/disable your features,
94-
[check out this great package which makes it much easier.](https://github.com/sindresorhus/yn)
102+
> Note 2: This package has built-in [yn](https://github.com/sindresorhus/yn) support which mean you don't have to do anything to get your env variable as Boolean value. You can also use `0/1`, `y/n` or any other value supported by the package. This will also work when `queryString` is set to `true`.
95103
96104
Now you just need to change your environment variables an restart Nuxt to toggle your features!
97105

98-
### Important note on `publicRuntimeConfig` and Promise / function based toggles
106+
### Important note on `publicRuntimeConfig` and Promise / function based toggles
99107
**If you're using function/promise based toggles resolution, you should not use `publicRuntimeConfig`:**
100-
while it's technically *possible* to use a function in `runtimeConfig`, [it is not recommended](https://nuxtjs.org/guide/runtime-config/).
108+
while it's technically *possible* to use a function in `runtimeConfig`, [it is not recommended](https://nuxtjs.org/guide/runtime-config/).
109+
110+
**A function/promise based toggles resolution will NOT be resolved in the plugin, only on build.**
101111

102-
**A function/promise based toggles resolution will NOT be resolved in the plugin, only on build.**
112+
Instead you should either:
113+
* Use a Promise/Function in `featureToggle.toggles` like you did before
114+
* Switch to object mode in `publicRuntimeConfig.featureToggle.toggles`.
103115

104-
Instead you should either:
105-
* Use a Promise/Function in `featureToggle.toggles` like you did before
106-
* Switch to object mode in `publicRuntimeConfig.featureToggle.toggles`.
107-
108116
As now you can use environment variables and just restart the server, many people can get rid of Promises returning toggles depending on the environment.
109117

110118

lib/feature-toggle.vue

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
<template>
2-
<div v-if="canShow">
3-
<slot/>
4-
</div>
5-
</template>
6-
71
<script>
82
export default {
93
name: 'feature-toggle',
@@ -64,6 +58,9 @@ export default {
6458
(!isQueryStringAllowed || isQueryStringAllowed(this.$props))
6559
)
6660
}
61+
},
62+
render() {
63+
return this.canShow ? this.$slots.default : null;
6764
}
6865
}
69-
</script>
66+
</script>

lib/module.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ const defaultOptions = {
66
}
77

88
async function featureToggleModule (moduleOptions) {
9+
const { nuxt } = this
10+
911
const options = {
1012
...defaultOptions,
1113
...this.options['feature-toggle'],
@@ -14,6 +16,9 @@ async function featureToggleModule (moduleOptions) {
1416
...(this.publicRuntimeConfig && this.publicRuntimeConfig.featureToggle) || {}
1517
}
1618

19+
// Transpile yn
20+
nuxt.options.build.transpile.push('yn')
21+
1722
// It's not recommended to use functions for runtimeConfig
1823
// so it's best to allow resolving a Promise only in module
1924
// but not in plugin.

lib/plugin.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Vue from 'vue'
2+
import yn from 'yn'
23

34
const parseQueryToggles = (queryObject = {}, queryStringPrefix = '') => Object.entries(queryObject)
45
.filter(([key]) => key.startsWith(`${queryStringPrefix}_`))
@@ -7,6 +8,8 @@ const parseQueryToggles = (queryObject = {}, queryStringPrefix = '') => Object.e
78
[key.replace(`${queryStringPrefix}_`, '')]: value
89
}), {})
910

11+
const parseYn = (t) => Object.entries(t).reduce((acc, [key, value]) => { acc[key] = yn(value) ?? value; return acc }, {})
12+
1013
export default (ctx, inject) => {
1114
const { $config, route, app: { router } } = ctx
1215
const { toggles: _toggles, queryString: _queryString, queryStringPrefix } = JSON.parse(`<%= JSON.stringify(options) %>`)
@@ -18,23 +21,25 @@ export default (ctx, inject) => {
1821
if (router && route) {
1922
queryToggles = parseQueryToggles(route.query, queryStringPrefix)
2023
router.afterEach((to) => {
21-
featureToggle.toggles = {
24+
featureToggle.toggles = parseYn({
2225
..._toggles,
2326
...(runtimeConfig.toggles || {}),
2427
...parseQueryToggles(to.query, queryStringPrefix)
25-
}
28+
})
2629
})
2730
}
2831
}
32+
2933
const toggles = {
3034
..._toggles,
3135
...(runtimeConfig.toggles || {}),
3236
...queryToggles
3337
}
38+
3439
Vue.component('feature-toggle', () => import('./feature-toggle.vue'))
3540

3641
const featureToggle = {
37-
toggles,
42+
toggles: parseYn(toggles),
3843
queryString,
3944
queryStringPrefix,
4045
isQueryStringAllowed: (fn) => {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
}
4343
},
4444
"dependencies": {
45-
"vue": "^2.6.10"
45+
"vue": "^2.6.10",
46+
"yn": "^5.0.0"
4647
},
4748
"devDependencies": {
4849
"@babel/core": "npm:@babel/core",

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6457,3 +6457,8 @@ yargs@^15.3.1:
64576457
which-module "^2.0.0"
64586458
y18n "^4.0.0"
64596459
yargs-parser "^18.1.2"
6460+
6461+
yn@^5.0.0:
6462+
version "5.0.0"
6463+
resolved "https://registry.yarnpkg.com/yn/-/yn-5.0.0.tgz#63fc2e2e0056cf294397eed6ad4a3fbdf707f26f"
6464+
integrity sha512-+l37+9TyGEsyxGLaTg6QgYy5KnOp74ZZl4dPFLQpBWSkO99uBC5jnS0pOGwXFViPbiaEtWbParH2KrgWWF2duQ==

0 commit comments

Comments
 (0)