Skip to content

Commit 19a9673

Browse files
add targeting filter doc for js
1 parent aa3d02c commit 19a9673

File tree

5 files changed

+241
-1
lines changed

5 files changed

+241
-1
lines changed

articles/azure-app-configuration/feature-management-javascript-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ app.use((req, res, next) => {
526526
const targetingContextAccessor = {
527527
getTargetingContext: () => {
528528
// Get the current request from AsyncLocalStorage
529-
const request = requestContext.getStore();
529+
const request = requestAccesor.getStore();
530530
if (!request) {
531531
return undefined; // Return undefined if there's no current request
532532
}
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
---
2+
title: Roll out features to targeted audiences in a Node.js app
3+
titleSuffix: Azure App Configuration
4+
description: Learn how to enable staged rollout of features for targeted audiences in a Node.js application.
5+
ms.service: azure-app-configuration
6+
ms.devlang: javascript
7+
author: zhiyuanliang-ms
8+
ms.author: zhiyuanliang
9+
ms.topic: how-to
10+
ms.date: 06/17/2025
11+
---
12+
13+
# Roll out features to targeted audiences in an ASP.NET Core application
14+
15+
In this guide, you'll use the targeting filter to roll out a feature to targeted audiences for your Node.js application. For more information about the targeting filter, see [Roll out features to targeted audiences](./howto-targetingfilter.md).
16+
17+
## Prerequisites
18+
19+
- Create a [Node.js application with a feature flag](./quickstart-feature-flag-javascript.md).
20+
- A feature flag with targeting filter. [Create the feature flag](./howto-targetingfilter.md).
21+
22+
## Create a web application with a feature flag
23+
24+
In this section, you create a web application that uses the *Beta* feature flag to control the access to the beta version of the page.
25+
26+
1. Create a folder called `targeting-filter-tutorial` and initialize the project.
27+
28+
```bash
29+
mkdir targeting-filter-tutorial
30+
cd targeting-filter-tutorial
31+
npm init -y
32+
```
33+
34+
1. Install the following packages.
35+
36+
```bash
37+
npm install @azure/app-configuration-provider
38+
npm install @microsoft/feature-management
39+
npm install express
40+
```
41+
42+
1. Create a new file named *app.js* and add the following code.
43+
44+
```js
45+
const express = require("express");
46+
const app = express();
47+
48+
const appConfigEndpoint = process.env.AZURE_APPCONFIG_ENDPOINT;
49+
const { DefaultAzureCredential } = require("@azure/identity");
50+
const { load } = require("@azure/app-configuration-provider");
51+
const { FeatureManager, ConfigurationMapFeatureFlagProvider } = require("@microsoft/feature-management");
52+
53+
let appConfig;
54+
let featureManager;
55+
async function initializeConfig() {
56+
appConfig = await load(appConfigEndpoint, new DefaultAzureCredential(), {
57+
featureFlagOptions: {
58+
enabled: true,
59+
refresh: {
60+
enabled: true
61+
}
62+
}
63+
});
64+
65+
const featureFlagProvider = new ConfigurationMapFeatureFlagProvider(appConfig);
66+
featureManager = new FeatureManager(featureFlagProvider);
67+
}
68+
69+
function startServer() {
70+
// Use a middleware to refresh the configuration before each request
71+
app.use((req, res, next) => {
72+
appConfig.refresh();
73+
next();
74+
});
75+
76+
app.get("/", async (req, res) => {
77+
const { userId, groups } = req.query;
78+
const beta = await featureManager.isEnabled("Beta", { userId: userId, groups: groups ? groups.split(",") : [] });
79+
if (beta) {
80+
res.send(`
81+
<html>
82+
<head><title>Beta Page</title></head>
83+
<body style="display: flex; justify-content: center; align-items: center;">
84+
<h1 style="text-align: center; font-size: 5.0rem">This is a beta page.</h1>
85+
</body>
86+
</html>
87+
`);
88+
} else {
89+
res.send(`
90+
<html>
91+
<head><title>Home Page</title></head>
92+
<body style="display: flex; justify-content: center; align-items: center;">
93+
<h1 style="text-align: center; font-size: 5.0rem">Welcome.</h1>
94+
</body>
95+
</html>
96+
`);
97+
}
98+
});
99+
100+
const port = "8080";
101+
app.listen(port, () => {
102+
console.log(`Server is running at http://localhost:${port}`);
103+
});
104+
}
105+
106+
// Initialize the configuration and start the server
107+
initializeConfig()
108+
.then(() => {
109+
startServer();
110+
})
111+
.catch((error) => {
112+
console.error("Failed to load configuration:", error);
113+
process.exit(1);
114+
});
115+
```
116+
117+
## Enable targeting for the web application
118+
119+
A targeting context is required for feature evaluation with targeting. You can provide it as a parameter to the `featureManager.isEnabled` API explicitly. In the tutorial, we extract user information from query parameters of the request URL for simplicity.
120+
121+
### Targeting Context Accessor
122+
123+
In the web application, the targeting context can also be provided as an ambient context by implementing the [ITargetingContextAccessor](./feature-management-javascript-reference.md#itargetingcontextaccessor) interface.
124+
125+
1. Add the following code to your application:
126+
127+
```js
128+
// ...
129+
// existing code
130+
const app = express();
131+
132+
const { AsyncLocalStorage } = require("async_hooks");
133+
const requestAccessor = new AsyncLocalStorage();
134+
// Use a middleware to store request context
135+
app.use((req, res, next) => {
136+
// Store the request in AsyncLocalStorage for this request chain
137+
requestAccessor.run(req, () => {
138+
next();
139+
});
140+
});
141+
142+
// Create a targeting context accessor that retrieves user data from the current request
143+
const targetingContextAccessor = {
144+
getTargetingContext: () => {
145+
// Get the current request from AsyncLocalStorage
146+
const request = requestAccessor.getStore();
147+
if (!request) {
148+
return undefined;
149+
}
150+
const { userId, groups } = request.query;
151+
return {
152+
userId: userId,
153+
groups: groups ? groups.split(",") : []
154+
};
155+
}
156+
};
157+
158+
// existing code
159+
// ...
160+
```
161+
162+
1. When constructing the `FeatureManager`, pass the targeting cotnext accessor to the `FeatureManagerOptions`.
163+
164+
```js
165+
featureManager = new FeatureManager(featureFlagProvider, {
166+
targetingContextAccessor: targetingContextAccessor
167+
});
168+
```
169+
170+
1. Instead of explicitly passing the targeting context with each `isEnabled` call, the feature manager will retrieve the current user's targeting information from the targeting context accessor.
171+
172+
```js
173+
app.get("/", async (req, res) => {
174+
const beta = await featureManager.isEnabled("Beta");
175+
if (beta) {
176+
// existing code
177+
// ...
178+
} else {
179+
// existing code
180+
// ...
181+
}
182+
});
183+
```
184+
185+
For more information, go to [Using AsyncLocalStorage for request context](./feature-management-javascript-reference.md#using-asynclocalstorage-for-request-context).
186+
187+
## Targeting filter in action
188+
189+
1. Set the environment variable named **AZURE_APPCONFIG_ENDPOINT** to the endpoint of your App Configuration store found under the *Overview* of your store in the Azure portal.
190+
191+
If you use the Windows command prompt, run the following command and restart the command prompt to allow the change to take effect:
192+
193+
```cmd
194+
setx AZURE_APPCONFIG_ENDPOINT "<endpoint-of-your-app-configuration-store>"
195+
```
196+
197+
If you use PowerShell, run the following command:
198+
199+
```powershell
200+
$Env:AZURE_APPCONFIG_ENDPOINT = "<endpoint-of-your-app-configuration-store>"
201+
```
202+
203+
If you use macOS or Linux, run the following command:
204+
205+
```bash
206+
export AZURE_APPCONFIG_ENDPOINT='<endpoint-of-your-app-configuration-store>'
207+
```
208+
209+
1. Run the application.
210+
211+
```bash
212+
node app.js
213+
```
214+
215+
1. Open your browser and navigate to `localhost:8080`. You should see the default view of the app.
216+
217+
:::image type="content" source="media/howto-targetingfilter-javascript/beta-disabled.png" alt-text="Screenshot of the app, showing the default greeting message.":::
218+
219+
1. Use `userId` query parameter in the url to specify the user ID. Visit `localhost:8080/[email protected]`. You see the beta page, because `[email protected]` is specified as a targeted user.
220+
221+
:::image type="content" source="media/howto-targetingfilter-javascript/beta-enabled.png" alt-text="Screenshot of the app, showing the beta page.":::
222+
223+
1. Visit `localhost:8080/[email protected]`. You cannot see the beta page, because `[email protected]` is specified as an excluded user..
224+
225+
:::image type="content" source="media/howto-targetingfilter-javascript/beta-not-targeted.png" alt-text="Screenshot of the app, showing the default content.":::
226+
227+
## Next steps
228+
229+
To learn more about the feature filters, continue to the following documents.
230+
231+
> [!div class="nextstepaction"]
232+
> [Enable conditional features with feature filters](./howto-feature-filters.md)
233+
234+
> [!div class="nextstepaction"]
235+
> [Enable features on a schedule](./howto-timewindow-filter-aspnet-core.md)
236+
237+
For the full feature rundown of the JavaScript feature management library, continue to the following document.
238+
239+
> [!div class="nextstepaction"]
240+
> [.NET Feature Management](./feature-management-javascript-reference.md)
52.4 KB
Loading
66.3 KB
Loading
61.8 KB
Loading

0 commit comments

Comments
 (0)