Skip to content

Commit

Permalink
Merge branch 'canary' into fix/edge-runtime-not-found
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] authored Aug 7, 2023
2 parents d198821 + 033732a commit 1f407d3
Show file tree
Hide file tree
Showing 19 changed files with 1,352 additions and 33 deletions.
2 changes: 2 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ stages:
- script: node run-tests.js --type unit
condition: eq(variables['isDocsOnly'], 'No')
displayName: 'Run tests'
env:
NEXT_TEST_MODE: 'dev'

# - job: test_e2e_dev
# pool:
Expand Down
11 changes: 5 additions & 6 deletions packages/create-next-app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,9 @@ async function run(): Promise<void> {

if (!program.typescript && !program.javascript) {
if (ciInfo.isCI) {
// default to JavaScript in CI as we can't prompt to
// default to TypeScript in CI as we can't prompt to
// prevent breaking setup flows
program.typescript = false
program.javascript = true
program.typescript = getPrefOrDefault('typescript')
} else {
const styledTypeScript = blue('TypeScript')
const { typescript } = await prompts(
Expand Down Expand Up @@ -295,7 +294,7 @@ async function run(): Promise<void> {
!process.argv.includes('--no-eslint')
) {
if (ciInfo.isCI) {
program.eslint = true
program.eslint = getPrefOrDefault('eslint')
} else {
const styledEslint = blue('ESLint')
const { eslint } = await prompts({
Expand All @@ -317,7 +316,7 @@ async function run(): Promise<void> {
!process.argv.includes('--no-tailwind')
) {
if (ciInfo.isCI) {
program.tailwind = false
program.tailwind = getPrefOrDefault('tailwind')
} else {
const tw = blue('Tailwind CSS')
const { tailwind } = await prompts({
Expand All @@ -339,7 +338,7 @@ async function run(): Promise<void> {
!process.argv.includes('--no-src-dir')
) {
if (ciInfo.isCI) {
program.srcDir = false
program.srcDir = getPrefOrDefault('srcDir')
} else {
const styledSrcDir = blue('`src/` directory')
const { srcDir } = await prompts({
Expand Down
10 changes: 5 additions & 5 deletions packages/next/src/build/swc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ interface TurboEngineOptions {
memoryLimit?: number
}

interface Issue {
export interface Issue {
severity: string
category: string
filePath: string
Expand All @@ -449,7 +449,7 @@ interface Issue {
subIssues: Issue[]
}

interface Diagnostics {}
export interface Diagnostics {}

export type TurbopackResult<T = {}> = T & {
issues: Issue[]
Expand All @@ -462,19 +462,19 @@ interface Middleware {
matcher?: string[]
}

interface Entrypoints {
export interface Entrypoints {
routes: Map<string, Route>
middleware?: Middleware
pagesDocumentEndpoint: Endpoint
pagesAppEndpoint: Endpoint
pagesErrorEndpoint: Endpoint
}

interface Update {
export interface Update {
update: unknown
}

interface Project {
export interface Project {
update(options: ProjectOptions): Promise<void>
entrypointsSubscribe(): AsyncIterableIterator<TurbopackResult<Entrypoints>>
hmrEvents(identifier: string): AsyncIterableIterator<TurbopackResult<Update>>
Expand Down
43 changes: 43 additions & 0 deletions packages/third-parties/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Experimental `@next/third-parties`

`@next/third-parties` is a collection of components and utilities that can be used to efficiently load third-party libraries into your Next.js application.

> Note: `@next/third-parties` is still experimental and under active development.
# Usage

## Google Third-Parties

### YouTube Embed

The `YoutubeEmbed` component is used to load and display a YouTube embed. This component loads faster by using [lite-youtube-embed](https://github.com/paulirish/lite-youtube-embed) under the hood.

```js
import { YoutubeEmbed } from '@next/third-parties/google'

export default function Page() {
return <YoutubeEmbed videoid="ogfYd705cRs" height={400} />
}
```

### Google Maps Embed

The `GoogleMapsEmbed` component can be used to add a [Google Maps Embed](https://developers.google.com/maps/documentation/embed/get-started) to your page. By default, it uses the `loading` attribute to lazy-load below the fold.

```js
import { GoogleMapsEmbed } from '@next/third-parties/google'

export default function Page() {
return (
<GoogleMapsEmbed
apiKey="XYZ"
height={200}
width="100%"
mapMode="place"
parameters="q=Brooklyn+Bridge,New+York,NY"
/>
)
}
```

To get a better idea of how these components work, take a look at this [demo](https://test-next-script-housseindjirdeh.vercel.app/). <!--- TODO: Replace with a better demo page -->
8 changes: 6 additions & 2 deletions packages/third-parties/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
"url": "vercel/next.js",
"directory": "packages/third-parties"
},
"main": "dist/index.js",
"exports": {
"./google": "./dist/google/index.js"
},
"files": [
"dist"
],
"license": "MIT",
"scripts": {
"manual-build": "rm -rf dist && tsc -d -p tsconfig.json && node scripts/update-third-parties",
"build": "rm -rf dist && tsc -d -p tsconfig.json",
"prepublishOnly": "cd ../../ && turbo run build",
"updateThirdParties": "rm -rf src/**/index.tsx && node scripts/update-third-parties",
"dev": "tsc -d -w -p tsconfig.json",
"typescript": "tsec --noEmit -p tsconfig.json"
},
Expand Down
20 changes: 14 additions & 6 deletions packages/third-parties/scripts/update-third-parties.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ function generateComponent(thirdParty) {
let props = ''

if (stylesheets?.length > 0) {
props += ` stylesheets={${JSON.stringify(stylesheets)}}`
// TODO: Remove ts-ignore after new <Script> component is published
// New <Script> accepts stylesheet as a param. Otherwise it throws error
props += `
// @ts-ignore
stylesheets={${JSON.stringify(stylesheets)}}`
}

return scripts
Expand Down Expand Up @@ -57,15 +61,18 @@ function generateComponent(thirdParty) {
AllThirdParties[thirdParty]

thirdPartyFunctions += outdent`
// ${description}
export function ${thirdParty}(args: any) {
export function ${thirdParty}(args: Types.${thirdParty}) {
return (
<Base
<ThirdPartyScriptEmbed
${content ? 'height={args.height || null}' : ''}
${content ? 'width={args.width || null}' : ''}
${content ? `content={\`${content}\`}` : ''}>
${content ? `content={\`${content}\`}` : ''}
dataNtpc="${thirdParty}"
>
${scripts?.length > 0 ? insertScripts(id, scripts, stylesheets) : ''}
</Base>
</ThirdPartyScriptEmbed>
)
}
`
Expand Down Expand Up @@ -97,7 +104,8 @@ function generateComponent(thirdParty) {
import React from 'react'
import Script from 'next/script'
import Base from './base'
import ThirdPartyScriptEmbed from '../ThirdPartyScriptEmbed'
import * as Types from '../types/${dir}'
`
for (const thirdParty of Object.values(config)) {
thirdPartyFunctions += generateComponent(thirdParty)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import React from 'react'

export default function Base({
content,
height = null,
width = null,
children,
}: {
export type ScriptEmbed = {
content?: string
height?: number | null
width?: number | null
children?: React.ReactElement | React.ReactElement[]
}) {
dataNtpc?: string
}

export default function ThirdPartyScriptEmbed({
content,
height = null,
width = null,
children,
dataNtpc = '',
}: ScriptEmbed) {
return (
<>
{/* insert script children */}
Expand All @@ -22,6 +26,7 @@ export default function Base({
height: height != null ? `${height}px` : 'auto',
width: width != null ? `${width}px` : 'auto',
}}
data-ntpc={dataNtpc}
dangerouslySetInnerHTML={{ __html: content }}
/>
)}
Expand Down
40 changes: 40 additions & 0 deletions packages/third-parties/src/google/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* This is an autogenerated file by update-third-parties.js
*/
import React from 'react'
import Script from 'next/script'

import ThirdPartyScriptEmbed from '../ThirdPartyScriptEmbed'
import * as Types from '../types/google'

// Embed a Google Maps embed on your webpage
export function GoogleMapsEmbed(args: Types.GoogleMapsEmbed) {
return (
<ThirdPartyScriptEmbed
height={args.height || null}
width={args.width || null}
content={`<iframe loading="lazy" src="https://www.google.com/maps/embed/v1/${args.mapMode}?key=${args.apiKey}&${args.parameters}" width=${args.width} height=${args.height} style=${args.style} allowfullscreen=${args.allowfullscreen} referrerpolicy="no-referrer-when-downgrade"></iframe>`}
dataNtpc="GoogleMapsEmbed"
></ThirdPartyScriptEmbed>
)
}
// Embed a YouTube embed on your webpage.
export function YoutubeEmbed(args: Types.YoutubeEmbed) {
return (
<ThirdPartyScriptEmbed
height={args.height || null}
width={args.width || null}
content={`<lite-youtube videoid=${args.videoid} playlabel=${args.playlabel}></lite-youtube>`}
dataNtpc="YoutubeEmbed"
>
<Script
src={`https://cdn.jsdelivr.net/gh/paulirish/lite-youtube-embed@master/src/lite-yt-embed.js`}
strategy="lazyOnload"
// @ts-ignore
stylesheets={[
'https://cdn.jsdelivr.net/gh/paulirish/lite-youtube-embed@master/src/lite-yt-embed.css',
]}
/>
</ThirdPartyScriptEmbed>
)
}
17 changes: 17 additions & 0 deletions packages/third-parties/src/types/google.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export type GoogleMapsEmbed = {
height?: number
width?: number
mapMode: 'place' | 'view' | 'directions' | 'streetview' | 'search'
apiKey: string
parameters: string
style: string
allowfullscreen: boolean
loading: 'eager' | 'lazy'
}

export type YoutubeEmbed = {
height?: number
width?: number
videoid: string
playlabel?: string
}
11 changes: 4 additions & 7 deletions packages/third-parties/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@
"sourceMap": true,
"strict": true,
"esModuleInterop": true,
"target": "es2020",
"lib": ["dom"],
"downlevelIteration": true,
"preserveWatchOutput": true,
"target": "es2019",
"outDir": "dist",
"jsx": "react",
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"moduleResolution": "Node16"
"resolveJsonModule": true,
"module": "commonjs",
"rootDir": "src"
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
Expand Down
18 changes: 18 additions & 0 deletions test/e2e/app-dir/third-parties/app/google-maps-embed/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { GoogleMapsEmbed } from '@next/third-parties/google'

const Page = () => {
return (
<div class="container">
<h1>Google Maps Embed</h1>
<GoogleMapsEmbed
apiKey="XYZ"
height={200}
width="100%"
mapMode="place"
parameters="q=Brooklyn+Bridge,New+York,NY"
/>
</div>
)
}

export default Page
7 changes: 7 additions & 0 deletions test/e2e/app-dir/third-parties/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Root({ children }: { children: React.ReactNode }) {
return (
<html>
<body>{children}</body>
</html>
)
}
12 changes: 12 additions & 0 deletions test/e2e/app-dir/third-parties/app/youtube-embed/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { YoutubeEmbed } from '@next/third-parties/google'

const Page = () => {
return (
<div class="container">
<h1>Youtube Embed</h1>
<YoutubeEmbed videoid="ogfYd705cRs" height={400} />
</div>
)
}

export default Page
32 changes: 32 additions & 0 deletions test/e2e/app-dir/third-parties/basic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { createNextDescribe } from 'e2e-utils'

createNextDescribe(
'@next/third-parties basic usage',
{
files: __dirname,
dependencies: {
'@next/third-parties': 'canary',
},
},
({ next }) => {
it('renders YoutubeEmbed', async () => {
const $ = await next.render$('/youtube-embed')

const baseContainer = $('[data-ntpc="YoutubeEmbed"]')
const youtubeContainer = $('lite-youtube')
expect(baseContainer.length).toBe(1)
expect(youtubeContainer.length).toBe(1)
})

it('renders GoogleMapsEmbed', async () => {
const $ = await next.render$('/google-maps-embed')

const baseContainer = $('[data-ntpc="GoogleMapsEmbed"]')
const mapContainer = $(
'[src="https://www.google.com/maps/embed/v1/place?key=XYZ&q=Brooklyn+Bridge,New+York,NY"]'
)
expect(baseContainer.length).toBe(1)
expect(mapContainer.length).toBe(1)
})
}
)
Loading

0 comments on commit 1f407d3

Please sign in to comment.