-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e9abcef
commit 889f278
Showing
23 changed files
with
15,695 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
OPTIMIZELY_SDK_KEY=your_sdk_key |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
**NOTICE TO CONTRIBUTORS** | ||
|
||
This repository is not actively monitored and any pull requests made to this repository will be closed/ignored. | ||
|
||
Please submit the pull request to [edgio-docs/edgio-examples](https://github.com/edgio-docs/edgio-examples) instead. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: Deploy to Edgio | ||
|
||
on: | ||
workflow_dispatch: | ||
push: | ||
|
||
jobs: | ||
deploy-to-edgio: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-node@v3 | ||
with: | ||
node-version: 18 | ||
- run: if [ -f yarn.lock ]; then yarn install; else npm ci; fi | ||
- run: if [ -f yarn.lock ]; then yarn edgio:deploy -- --token=$EDGIO_DEPLOY_TOKEN; else npm run edgio:deploy -- --token=$EDGIO_DEPLOY_TOKEN; fi | ||
env: | ||
EDGIO_DEPLOY_TOKEN: ${{secrets.EDGIO_DEPLOY_TOKEN}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts | ||
|
||
# Edgio generated build directory | ||
/.edgio | ||
/node_modules | ||
lib/optimizely/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). | ||
|
||
## Getting Started | ||
|
||
First, run the development server: | ||
|
||
```bash | ||
npm run dev | ||
# or | ||
yarn dev | ||
# or | ||
pnpm dev | ||
# or | ||
bun dev | ||
``` | ||
|
||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. | ||
|
||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. | ||
|
||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. | ||
|
||
## Learn More | ||
|
||
To learn more about Next.js, take a look at the following resources: | ||
|
||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. | ||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. | ||
|
||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! | ||
|
||
## Deploy on Vercel | ||
|
||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. | ||
|
||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
import { | ||
createInstance, | ||
eventDispatcher, | ||
} from '@optimizely/optimizely-sdk/dist/optimizely.lite.min.js'; | ||
import optimizelyDatafile from '../lib/optimizely/datafile.json'; | ||
|
||
const CLIENT_ENGINE = 'EDGIO_EF'; | ||
const COOKIE_NAME = 'optimizely_visitor_id'; | ||
|
||
/** | ||
* An example edge function which forwards the request to the origin. | ||
* See routes.js for how this function is configured to run for requests to "/". | ||
*/ | ||
|
||
export async function handleHttpRequest(request, context) { | ||
// Fetch user Id from the cookie if available so a returning user from same browser session always sees the same variation. | ||
const userId = | ||
request.headers | ||
.get('Cookie') | ||
?.split(';') | ||
.find((cookie) => cookie.trim().startsWith(`${COOKIE_NAME}=`)) | ||
?.split('=')[1] || `user-${new Date().getTime()}`; | ||
|
||
console.log(JSON.stringify(context, null, 2)); | ||
const url = new URL('/', request.url); | ||
const resp = await fetch(url, { | ||
edgio: { | ||
origin: 'edgio_self', | ||
}, | ||
}); | ||
|
||
// handle the response as needed | ||
// For example, to inject some html into the body: | ||
const html = await resp.text(); | ||
|
||
// Create Optimizely instance using datafile downloaded at build time. | ||
const instance = createInstance({ | ||
datafile: optimizelyDatafile, | ||
clientEngine: CLIENT_ENGINE, | ||
eventDispatcher, | ||
}); | ||
|
||
// Return the original HTML if the instance is not created. | ||
if (!instance) { | ||
return resp; | ||
} | ||
|
||
await instance.onReady(); | ||
|
||
// Create Optimizely User Context | ||
const userContext = instance.createUserContext(userId.toString()); | ||
|
||
// Decide variation for the flag. | ||
const decision = userContext.decide('foo_flag'); | ||
|
||
console.log(`[OPTIMIZELY] userId: ${userId}`); | ||
console.log( | ||
`[OPTIMIZELY] flag 'foo_flag' is ${ | ||
decision.enabled ? 'enabled' : 'disabled' | ||
} for the user ${userId}` | ||
); | ||
|
||
// To send the response to the client with the new HTML but the same headers as the origin response: | ||
return new Response(html, { | ||
...resp, | ||
headers: { | ||
...resp.headers, | ||
'x-edge-function': 'main.js', | ||
}, | ||
}); | ||
} | ||
|
||
// Check if setTimeout is already available (in case of running in an environment that has it) | ||
|
||
let timers = new Map(); | ||
let nextTimerId = 1; | ||
|
||
(function () { | ||
var timerQueue = []; | ||
var nextTimerId = 0; | ||
|
||
function runTimers() { | ||
var now = Date.now(); | ||
var nextCheck = null; | ||
|
||
// Run due timers | ||
for (var i = 0; i < timerQueue.length; i++) { | ||
var timer = timerQueue[i]; | ||
if (timer.time <= now) { | ||
timer.callback.apply(null, timer.args); | ||
if (timer.repeating) { | ||
timer.time = now + timer.delay; // schedule next run | ||
nextCheck = | ||
nextCheck !== null ? Math.min(nextCheck, timer.time) : timer.time; | ||
} else { | ||
timerQueue.splice(i--, 1); // remove non-repeating timer | ||
} | ||
} else { | ||
nextCheck = | ||
nextCheck !== null ? Math.min(nextCheck, timer.time) : timer.time; | ||
} | ||
} | ||
|
||
// Schedule next check | ||
if (nextCheck !== null) { | ||
var delay = Math.max(nextCheck - Date.now(), 0); | ||
setTimeout(runTimers, delay); | ||
} | ||
} | ||
|
||
global.setTimeout = function (callback, delay, ...args) { | ||
var timerId = ++nextTimerId; | ||
var timer = { | ||
id: timerId, | ||
callback: callback, | ||
time: Date.now() + delay, | ||
args: args, | ||
repeating: false, | ||
delay: delay, | ||
}; | ||
timerQueue.push(timer); | ||
return timerId; | ||
}; | ||
|
||
global.clearTimeout = function (timerId) { | ||
for (var i = 0; i < timerQueue.length; i++) { | ||
if (timerQueue[i].id === timerId) { | ||
timerQueue.splice(i, 1); | ||
break; | ||
} | ||
} | ||
}; | ||
|
||
global.queueMicrotask = function (callback) { | ||
Promise.resolve() | ||
.then(callback) | ||
.catch((err) => | ||
setTimeout(() => { | ||
throw err; | ||
}) | ||
); | ||
}; | ||
|
||
setTimeout(runTimers, 0); | ||
})(); | ||
|
||
//@ts-ignore | ||
|
||
// export async function middleware(req: NextRequest, ev: NextFetchEvent) { | ||
// // Fetch user Id from the cookie if available so a returning user from same browser session always sees the same variation. | ||
// const userId = req.cookies.get(COOKIE_NAME)?.value || crypto.randomUUID() | ||
|
||
// // Create Optimizely instance using datafile downloaded at build time. | ||
// const instance = createInstance({ | ||
// datafile: optimizelyDatafile, | ||
// clientEngine: VERCEL_EDGE_CLIENT_ENGINE, | ||
// eventDispatcher: { | ||
// dispatchEvent: ({ url, params }: { url: string; params: any }) => { | ||
// // Tell edge function to wait for this promise to fullfill. | ||
// ev.waitUntil( | ||
// fetch(url, { | ||
// method: 'POST', | ||
// body: JSON.stringify(params), | ||
// }) | ||
// ) | ||
// }, | ||
// }, | ||
// }) | ||
|
||
// // Create Optimizely User Context | ||
// const userContext = instance!.createUserContext(userId.toString()) | ||
|
||
// // Decide variation for the flag. | ||
// const decision = userContext!.decide('product_sort') | ||
|
||
// // Fetch datafile revision for debugging. | ||
// const revision = instance!.getOptimizelyConfig()!.revision | ||
|
||
// console.log(`[OPTIMIZELY] Datafile Revision: ${revision}`) | ||
// console.log(`[OPTIMIZELY] userId: ${userId}`) | ||
// console.log( | ||
// `[OPTIMIZELY] flag 'product_sort' is ${ | ||
// decision.enabled ? 'enabled' : 'disabled' | ||
// } for the user ${userId}` | ||
// ) | ||
// console.log( | ||
// `[OPTIMIZELY] User ${userId} was bucketed in to variation ${decision.variationKey}` | ||
// ) | ||
// console.log(`[OPTIMIZELY] sort_method is ${decision.variables.sort_method}`) | ||
|
||
// // Rewriting the path based on sort_method. The default is Alphabetical. | ||
// req.nextUrl.pathname = | ||
// decision.variables.sort_method === 'popular_first' ? '/popular' : '/' | ||
// let res = NextResponse.rewrite(req.nextUrl) | ||
|
||
// if (!req.cookies.has(COOKIE_NAME)) { | ||
// // Saving userId in the cookie so that the decision sticks for subsequent visits. | ||
// res.cookies.set(COOKIE_NAME, userId) | ||
// } | ||
|
||
// return res | ||
// } |
Oops, something went wrong.