在本指南中,您將使用目標篩選將功能推送至 Node.js 應用程式的目標用戶。 如需目標篩選的詳細資訊,請參閱向目標受眾推出功能。
先決條件
- 具有有效訂閱的 Azure 帳戶。 免費建立一個。
- 應用程式組態存放區,如 建立存放區指引所示。
- 具有目標篩選的 Beta 功能旗標。 建立功能旗標。
- Node.js的 LTS 版本 。
使用功能旗標建立 Web 應用程式
在本節中,您會建立使用 Beta 功能旗標 來控制網頁 Beta 版存取權的 Web 應用程式。
設定 Node.js Express 專案
建立名為
targeting-filter-tutorial的資料夾,並初始化專案。mkdir targeting-filter-tutorial cd targeting-filter-tutorial npm init -y安裝下列套件。
npm install @azure/app-configuration-provider npm install @microsoft/feature-management npm install express建立名為 app.js 的新檔案,並新增下列程序代碼。
const express = require("express"); const server = express(); const port = "8080"; server.listen(port, () => { console.log(`Server is running at http://localhost:${port}`); });
連接到 Azure 應用程式設定
更新 app.js 並新增下列程序代碼。
// Existing code ... const appConfigEndpoint = process.env.AZURE_APPCONFIG_ENDPOINT; const { DefaultAzureCredential } = require("@azure/identity"); const { load } = require("@azure/app-configuration-provider"); const { FeatureManager, ConfigurationMapFeatureFlagProvider } = require("@microsoft/feature-management"); let appConfig; let featureManager; async function initializeConfig() { // Load feature flags from App Configuration. appConfig = await load(appConfigEndpoint, new DefaultAzureCredential(), { featureFlagOptions: { enabled: true, refresh: { enabled: true } } }); // Create feature manager with feature flag provider that accesses feature flags from App Configuration. featureManager = new FeatureManager( new ConfigurationMapFeatureFlagProvider(appConfig)); } // Use a middleware to refresh the configuration before each request. server.use((req, res, next) => { appConfig.refresh(); next(); }); // Existing code ...您可以連線到 Azure 應用程式組態以載入功能旗標、啟用自動重新整理,以及建立
FeatureManager物件以供稍後存取功能旗標。 中間件會在每個要求之前新增以重新整理組態。更新程式代碼,以確保 Express 伺服器只有在設定成功初始化之後才會啟動。
// Existing code ... initializeConfig() .then(() => { // Start the express server. server.listen(port, () => { console.log(`Server is running at http://localhost:${port}`); }); })
啟用功能旗標
將下列程式代碼新增至 app.js 檔案,以設定 Express 伺服器的路由處理程式。 伺服器會根據 Beta 功能旗標是否啟用,提供不同的內容。
// Existing code ...
server.get("/", async (req, res) => {
const isBetaEnabled = await featureManager.isEnabled("Beta");
const [title, message] = isBetaEnabled
? ["Beta Page", "This is a beta page."]
: ["Home Page", "Welcome."];
res.send(
`<!DOCTYPE html>
<html>
<head><title>${title}</title></head>
<body style="display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0;">
<h1 style="text-align: center; font-size: 5rem;">${message}</h1>
</body>
</html>`
);
});
initializeConfig()
// Existing code ...
啟用 Web 應用程式的目標鎖定
當評估具有目標功能的特徵時,需要有一個目標定位的上下文環境。 若要明確提供此功能評估的這個內容,您可以將它當做參數傳遞至 featureManager.isEnabled 方法。
const isBetaEnabled = await featureManager.isEnabled("Beta", { userId: "UserA", groups: ["Group1"] });
在 Web 應用程式中,目標內容也可以藉由實作 ITargetingContextAccessor 介面來提供作為環境內容。 環境目標上下文表示目標資訊會自動從周遭環境(例如目前的 HTTP 請求)擷取,而不需要明確地將其傳遞至每個 featureManager.isEnabled() 呼叫。
您在本教學課程中使用環境型目標內容。
在 Express 伺服器宣告之後新增下列程式代碼。 它會使用
AsyncLocalStorage來儲存目前的要求,讓功能管理員能夠透過目標內容存取子回呼自動擷取目標內容。 如需詳細資訊,請參閱 使用 AsyncLocalStorage 進行請求內容。const express = require("express"); const server = express(); const port = 8080; const { AsyncLocalStorage } = require("async_hooks"); const requestAccessor = new AsyncLocalStorage(); // Use a middleware to store request context. server.use((req, res, next) => { // Store the request in AsyncLocalStorage for this request chain. requestAccessor.run(req, () => { next(); }); }); // Create a targeting context accessor that retrieves user data from the current request. const targetingContextAccessor = { getTargetingContext: () => { // Get the current request from AsyncLocalStorage. const request = requestAccessor.getStore(); if (!request) { return undefined; } const { userId, groups } = request.query; return { userId: userId, groups: groups ? groups.split(",") : [] }; } }; // Existing code ...在建構
FeatureManager時,將目標上下文存取器傳遞至FeatureManagerOptions。featureManager = new FeatureManager( new ConfigurationMapFeatureFlagProvider(appConfig), { targetingContextAccessor: targetingContextAccessor });
完成上述步驟之後,您的 app.js 檔案現在應該包含下列完整的實作。
const express = require("express");
const server = express();
const port = 8080;
const { AsyncLocalStorage } = require("async_hooks");
const requestAccessor = new AsyncLocalStorage();
// Use a middleware to store request context
server.use((req, res, next) => {
// Store the request in AsyncLocalStorage for this request chain
requestAccessor.run(req, () => {
next();
});
});
// Create a targeting context accessor that retrieves user data from the current request
const targetingContextAccessor = {
getTargetingContext: () => {
// Get the current request from AsyncLocalStorage
const request = requestAccessor.getStore();
if (!request) {
return undefined;
}
const { userId, groups } = request.query;
return {
userId: userId,
groups: groups ? groups.split(",") : []
};
}
};
const appConfigEndpoint = process.env.AZURE_APPCONFIG_ENDPOINT;
const { DefaultAzureCredential } = require("@azure/identity");
const { load } = require("@azure/app-configuration-provider");
const { FeatureManager, ConfigurationMapFeatureFlagProvider } = require("@microsoft/feature-management");
let appConfig;
let featureManager;
async function initializeConfig() {
// Load feature flags from App Configuration.
appConfig = await load(appConfigEndpoint, new DefaultAzureCredential(), {
featureFlagOptions: {
enabled: true,
refresh: {
enabled: true
}
}
});
// Create feature manager with feature flag provider that accesses feature flags from App Configuration and targeting context accessor.
featureManager = new FeatureManager(
new ConfigurationMapFeatureFlagProvider(appConfig),
{
targetingContextAccessor: targetingContextAccessor
});
}
// Use a middleware to refresh the configuration before each request
server.use((req, res, next) => {
appConfig.refresh();
next();
});
server.get("/", async (req, res) => {
const isBetaEnabled = await featureManager.isEnabled("Beta");
const [title, message] = isBetaEnabled
? ["Beta Page", "This is a beta page."]
: ["Home Page", "Welcome."];
res.send(
`<!DOCTYPE html>
<html>
<head><title>${title}</title></head>
<body style="display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0;">
<h1 style="text-align: center; font-size: 5rem;">${message}</h1>
</body>
</html>`
);
});
// Initialize the configuration and start the server
initializeConfig()
.then(() => {
// Start the express server.
server.listen(port, () => {
console.log(`Server is running at http://localhost:${port}`);
});
})
作用中的目標篩選
將名為 AZURE_APPCONFIG_ENDPOINT 的環境變數設定為在 Azure 入口網站中,於市集的 總覽 底下找到的應用程式組態存放區端點。
如果您使用 Windows 命令提示字元,請執行下列命令,然後重新啟動命令提示字元以讓變更生效:
setx AZURE_APPCONFIG_ENDPOINT "<endpoint-of-your-app-configuration-store>"如果您使用 PowerShell,請執行下列命令:
$Env:AZURE_APPCONFIG_ENDPOINT = "<endpoint-of-your-app-configuration-store>"如果您使用 macOS 或 Linux,請執行下列命令:
export AZURE_APPCONFIG_ENDPOINT='<endpoint-of-your-app-configuration-store>'執行應用程式。
node app.js請開啟瀏覽器,然後瀏覽至
localhost:8080。 您應該會看到應用程式的預設檢視。
-
- 將 新增
userId為 URL 中的查詢參數,以指定使用者識別碼。 請造訪localhost:8080/?userId=test@contoso.com。 您會看到 Beta 頁面,因為test@contoso.com已指定為目標使用者。
- 將 新增
請造訪
localhost:8080/?userId=testuser@contoso.com。 您無法看到 Beta 頁面,因為testuser@contoso.com已指定為排除的使用者。
後續步驟
若要深入了解功能篩選,請繼續檢視下列文件。
如需 JavaScript 功能管理程式庫的完整功能摘要,請繼續參閱下列文件。