Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add experimental.urlImports option (#30079)
Co-authored-by: Lee Robinson <me@leerob.io> Co-authored-by: Rich Haines <hello@richardhaines.dev>
- Loading branch information
1 parent
be2156f
commit d07107f
Showing
17 changed files
with
207 additions
and
2 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,37 @@ | ||
--- | ||
description: Configure Next.js to allow importing modules from external URLs. | ||
--- | ||
|
||
# URL imports | ||
|
||
URL Imports are an experimental feature that allows you to import modules directly from external servers (instead of from the local disk). | ||
|
||
To opt-in, add the allowed URL prefixes inside `next.config.js`: | ||
|
||
```js | ||
module.exports = { | ||
experimental: { | ||
urlImports: ['https://example.com/modules/'], | ||
}, | ||
} | ||
``` | ||
|
||
Then, you can import modules directly from URLs: | ||
|
||
```js | ||
import { a, b, c } from 'https://example.com/modules/' | ||
``` | ||
|
||
URL Imports can be used everywhere normal package imports can be used. | ||
|
||
## Lockfile | ||
|
||
When using URL imports, Next.js will create a lockfile in the `next.lock` directory. | ||
This directory is intended to be committed to Git and should **not be included** in your `.gitignore` file. | ||
|
||
- When running `next dev`, Next.js will download and add all newly discovered URL Imports to your lockfile | ||
- When running `next build`, Next.js will use only the lockfile to build the application for production | ||
|
||
Typically, no network requests are needed and any outdated lockfile will cause the build to fail. | ||
One exception is resources that respond with `Cache-Control: no-cache`. | ||
These resources will have a `no-cache` entry in the lockfile and will always be fetched from the network on each build. |
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
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
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
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 @@ | ||
# this is only needed for the test case | ||
# Do not ignore that in real apps | ||
next.lock |
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 @@ | ||
module.exports = { | ||
experimental: { | ||
urlImports: ['http://localhost:12345/'], | ||
}, | ||
} |
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 @@ | ||
import value from 'http://localhost:12345/value4.js' | ||
|
||
export default (req, res) => { | ||
res.json({ value: value }) | ||
} |
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,17 @@ | ||
import value from 'http://localhost:12345/value1.js' | ||
|
||
export async function getStaticProps() { | ||
return { | ||
props: { | ||
value, | ||
}, | ||
} | ||
} | ||
|
||
export default function Index({ value: staticValue }) { | ||
return ( | ||
<div> | ||
Hello {staticValue}+{value} | ||
</div> | ||
) | ||
} |
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,17 @@ | ||
import value from 'http://localhost:12345/value2.js' | ||
|
||
export function getServerSideProps() { | ||
return { | ||
props: { | ||
value, | ||
}, | ||
} | ||
} | ||
|
||
export default function Index({ value: serverValue }) { | ||
return ( | ||
<div> | ||
Hello {serverValue}+{value} | ||
</div> | ||
) | ||
} |
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,9 @@ | ||
import value from 'http://localhost:12345/value3.js' | ||
|
||
export default function Index(props) { | ||
return ( | ||
<div> | ||
Hello {value}+{value} | ||
</div> | ||
) | ||
} |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 @@ | ||
export default 42 // 1 |
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 @@ | ||
export default 42 // 2 |
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 @@ | ||
export default 42 // 3 |
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 @@ | ||
export default 42 // 4 |
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,89 @@ | ||
/* eslint-disable no-loop-func */ | ||
/* eslint-env jest */ | ||
|
||
import fs from 'fs-extra' | ||
import { join } from 'path' | ||
import { | ||
nextBuild, | ||
findPort, | ||
nextStart, | ||
killApp, | ||
renderViaHTTP, | ||
fetchViaHTTP, | ||
launchApp, | ||
getBrowserBodyText, | ||
check, | ||
startStaticServer, | ||
stopApp, | ||
} from 'next-test-utils' | ||
import webdriver from 'next-webdriver' | ||
|
||
jest.setTimeout(1000 * 60 * 2) | ||
const appDir = join(__dirname, '../') | ||
|
||
describe(`Handle url imports`, () => { | ||
let staticServer | ||
let staticServerPort | ||
beforeAll(async () => { | ||
await fs.remove(join(appDir, 'next.lock')) | ||
staticServerPort = 12345 | ||
staticServer = await startStaticServer( | ||
join(appDir, 'source'), | ||
undefined, | ||
staticServerPort | ||
) | ||
}) | ||
afterAll(async () => { | ||
await stopApp(staticServer) | ||
}) | ||
|
||
for (const dev of [true, false]) { | ||
describe(dev ? 'with next dev' : 'with next build', () => { | ||
let appPort | ||
let app | ||
beforeAll(async () => { | ||
await fs.remove(join(appDir, '.next')) | ||
if (dev) { | ||
appPort = await findPort() | ||
app = await launchApp(appDir, appPort) | ||
} else { | ||
await nextBuild(appDir) | ||
appPort = await findPort() | ||
app = await nextStart(appDir, appPort) | ||
} | ||
}) | ||
afterAll(async () => { | ||
await killApp(app) | ||
}) | ||
const expectedServer = /Hello <!-- -->42<!-- -->\+<!-- -->42/ | ||
const expectedClient = new RegExp( | ||
expectedServer.source.replace(/<!-- -->/g, '') | ||
) | ||
|
||
for (const page of ['/static', '/ssr', '/ssg']) { | ||
it(`should render the ${page} page`, async () => { | ||
const html = await renderViaHTTP(appPort, page) | ||
expect(html).toMatch(expectedServer) | ||
}) | ||
|
||
it(`should client-render the ${page} page`, async () => { | ||
let browser | ||
try { | ||
browser = await webdriver(appPort, page) | ||
await check(() => getBrowserBodyText(browser), expectedClient) | ||
} finally { | ||
await browser.close() | ||
} | ||
}) | ||
} | ||
|
||
it('should respond on value api', async () => { | ||
const data = await fetchViaHTTP(appPort, '/api/value').then( | ||
(res) => res.ok && res.json() | ||
) | ||
|
||
expect(data).toEqual({ value: 42 }) | ||
}) | ||
}) | ||
} | ||
}) |
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