Skip to content

Commit

Permalink
Merge branch 'canary' into fix-52935
Browse files Browse the repository at this point in the history
  • Loading branch information
samcx authored Mar 17, 2024
2 parents 848510f + bbd3543 commit 97a8e66
Show file tree
Hide file tree
Showing 44 changed files with 490 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ The two layouts would be nested as such:
>
> - `.js`, `.jsx`, or `.tsx` file extensions can be used for Layouts.
> - Only the root layout can contain `<html>` and `<body>` tags.
> - When a `layout.js` and `page.js` file are defined in the same folder. The layout will wrap the page.
> - When a `layout.js` and `page.js` file are defined in the same folder, the layout will wrap the page.
> - Layouts are [Server Components](/docs/app/building-your-application/rendering/server-components) by default but can be set to a [Client Component](/docs/app/building-your-application/rendering/client-components).
> - Layouts can fetch data. View the [Data Fetching](/docs/app/building-your-application/data-fetching) section for more information.
> - Passing data between a parent layout and its children is not possible. However, you can fetch the same data in a route more than once, and React will [automatically dedupe the requests](/docs/app/building-your-application/caching#request-memoization) without affecting performance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export const revalidate = false
// false | 0 | number
```

- **`false`**: (default) The default heuristic to cache any `fetch` requests that set their `cache` option to `'force-cache'` or are discovered before a [dynamic function](/docs/app/building-your-application/rendering/server-components#server-rendering-strategies#dynamic-functions) is used. Semantically equivalent to `revalidate: Infinity` which effectively means the resource should be cached indefinitely. It is still possible for individual `fetch` requests to use `cache: 'no-store'` or `revalidate: 0` to avoid being cached and make the route dynamically rendered. Or set `revalidate` to a positive number lower than the route default to increase the revalidation frequency of a route.
- **`false`** (default): The default heuristic to cache any `fetch` requests that set their `cache` option to `'force-cache'` or are discovered before a [dynamic function](/docs/app/building-your-application/rendering/server-components#server-rendering-strategies#dynamic-functions) is used. Semantically equivalent to `revalidate: Infinity` which effectively means the resource should be cached indefinitely. It is still possible for individual `fetch` requests to use `cache: 'no-store'` or `revalidate: 0` to avoid being cached and make the route dynamically rendered. Or set `revalidate` to a positive number lower than the route default to increase the revalidation frequency of a route.
- **`0`**: Ensure a layout or page is always [dynamically rendered](/docs/app/building-your-application/rendering/server-components#dynamic-rendering) even if no dynamic functions or uncached data fetches are discovered. This option changes the default of `fetch` requests that do not set a `cache` option to `'no-store'` but leaves `fetch` requests that opt into `'force-cache'` or use a positive `revalidate` as is.
- **`number`**: (in seconds) Set the default revalidation frequency of a layout or page to `n` seconds.

Expand Down Expand Up @@ -142,7 +142,7 @@ export const fetchCache = 'auto'
// 'force-cache' | 'force-no-store' | 'default-no-store' | 'only-no-store'
```

- **`'auto'`** (default)- The default option to cache `fetch` requests before dynamic functions with the `cache` option they provide and not cache `fetch` requests after dynamic functions.
- **`'auto'`** (default): The default option to cache `fetch` requests before dynamic functions with the `cache` option they provide and not cache `fetch` requests after dynamic functions.
- **`'default-cache'`**: Allow any `cache` option to be passed to `fetch` but if no option is provided then set the `cache` option to `'force-cache'`. This means that even `fetch` requests after dynamic functions are considered static.
- **`'only-cache'`**: Ensure all `fetch` requests opt into caching by changing the default to `cache: 'force-cache'` if no option is provided and causing an error if any `fetch` requests use `cache: 'no-store'`.
- **`'force-cache'`**: Ensure all `fetch` requests opt into caching by setting the `cache` option of all `fetch` requests to `'force-cache'`.
Expand All @@ -166,16 +166,16 @@ export const fetchCache = 'auto'

```tsx filename="layout.tsx | page.tsx | route.ts" switcher
export const runtime = 'nodejs'
// 'edge' | 'nodejs'
// 'nodejs' | 'edge'
```

```js filename="layout.js | page.js | route.js" switcher
export const runtime = 'nodejs'
// 'edge' | 'nodejs'
// 'nodejs' | 'edge'
```

- **`nodejs`** (default)
- **`edge`**
- **`'nodejs'`** (default)
- **`'edge'`**

Learn more about the [Edge and Node.js runtimes](/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes).

Expand Down
1 change: 1 addition & 0 deletions docs/02-app/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Here are some common authentication solutions that support the App Router:

- [NextAuth.js](https://next-auth.js.org/configuration/nextjs#in-app-router)
- [Clerk](https://clerk.com/docs/quickstarts/nextjs)
- [Lucia](https://lucia-auth.com/getting-started/nextjs-app)
- [Auth0](https://github.com/auth0/nextjs-auth0#app-router)
- [Stytch](https://stytch.com/docs/example-apps/frontend/nextjs)
- [Kinde](https://kinde.com/docs/developer-tools/nextjs-sdk/)
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
"registry": "https://registry.npmjs.org/"
}
},
"version": "14.2.0-canary.24"
"version": "14.2.0-canary.26"
}
2 changes: 1 addition & 1 deletion packages/create-next-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-next-app",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"keywords": [
"react",
"next",
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-config-next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-config-next",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"description": "ESLint configuration used by Next.js.",
"main": "index.js",
"license": "MIT",
Expand All @@ -10,7 +10,7 @@
},
"homepage": "https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config",
"dependencies": {
"@next/eslint-plugin-next": "14.2.0-canary.24",
"@next/eslint-plugin-next": "14.2.0-canary.26",
"@rushstack/eslint-patch": "^1.3.3",
"@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.1",
"eslint-import-resolver-node": "^0.3.6",
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/eslint-plugin-next",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"description": "ESLint plugin for Next.js.",
"main": "dist/index.js",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/font/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/font",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"repository": {
"url": "vercel/next.js",
"directory": "packages/font"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-bundle-analyzer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/bundle-analyzer",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"main": "index.js",
"types": "index.d.ts",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-codemod/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/codemod",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-env/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/env",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"keywords": [
"react",
"next",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-mdx/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"main": "index.js",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-storybook/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-storybook",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-storybook"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-polyfill-module/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-module",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)",
"main": "dist/polyfill-module.js",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-polyfill-nomodule/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-nomodule",
"version": "14.2.0-canary.24",
"version": "14.2.0-canary.26",
"description": "A polyfill for non-dead, nomodule browsers.",
"main": "dist/polyfill-nomodule.js",
"license": "MIT",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ pub async fn parse_segment_config_from_source(

// Don't try parsing if it's not a javascript file, otherwise it will emit an
// issue causing the build to "fail".
if path.path.ends_with("d.ts")
if path.path.ends_with(".d.ts")
|| !(path.path.ends_with(".js")
|| path.path.ends_with(".jsx")
|| path.path.ends_with(".ts")
Expand Down
8 changes: 8 additions & 0 deletions packages/next-swc/crates/next-core/src/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ impl NextMode {
}
}

/// Returns the exports condition for the current mode.
pub fn condition(&self) -> &'static str {
match self {
NextMode::Development => "development",
NextMode::Build => "production",
}
}

/// Returns true if the development React runtime should be used.
pub fn is_react_development(&self) -> bool {
match self {
Expand Down
25 changes: 19 additions & 6 deletions packages/next-swc/crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ pub enum ClientContextType {
Other,
}

impl ClientContextType {
pub fn conditions(&self) -> &'static [&'static str] {
match self {
ClientContextType::Pages { .. } => &["next-client", "next-pages"],
ClientContextType::App { .. } => &["next-client", "next-app"],
ClientContextType::Fallback => &["next-client", "next-fallback"],
ClientContextType::Other => &["next-client", "next-other"],
}
}
}

#[turbo_tasks::function]
pub async fn get_client_resolve_options_context(
project_path: Vc<FileSystemPath>,
Expand All @@ -149,9 +160,11 @@ pub async fn get_client_resolve_options_context(
let next_client_fallback_import_map = get_next_client_fallback_import_map(ty);
let next_client_resolved_map =
get_next_client_resolved_map(project_path, project_path, *mode.await?);
let mut custom_conditions = vec![mode.await?.condition().to_string()];
custom_conditions.extend(ty.conditions().iter().map(ToString::to_string));
let module_options_context = ResolveOptionsContext {
enable_node_modules: Some(project_path.root().resolve().await?),
custom_conditions: vec![mode.await?.node_env().to_string()],
custom_conditions,
import_map: Some(next_client_import_map),
fallback_import_map: Some(next_client_fallback_import_map),
resolved_map: Some(next_client_resolved_map),
Expand Down Expand Up @@ -215,11 +228,11 @@ pub async fn get_client_module_options_context(
// foreign_code_context_condition. This allows to import codes from
// node_modules that requires webpack loaders, which next-dev implicitly
// does by default.
let foreign_webpack_rules = maybe_add_sass_loader(
next_config.sass_config(),
*next_config.webpack_rules().await?,
)
.await?;
let mut conditions = vec!["browser".to_string(), mode.await?.condition().to_string()];
conditions.extend(ty.conditions().iter().map(ToString::to_string));
let foreign_webpack_rules = *next_config.webpack_rules(conditions).await?;
let foreign_webpack_rules =
maybe_add_sass_loader(next_config.sass_config(), foreign_webpack_rules).await?;
let foreign_webpack_loaders = foreign_webpack_rules.map(|rules| {
WebpackLoadersOptions {
rules,
Expand Down
91 changes: 70 additions & 21 deletions packages/next-swc/crates/next-core/src/next_config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashSet;

use anyhow::{bail, Context, Result};
use indexmap::IndexMap;
use serde::{Deserialize, Deserializer, Serialize};
Expand Down Expand Up @@ -387,21 +389,32 @@ pub enum RemotePatternProtocal {
pub struct ExperimentalTurboConfig {
/// This option has been replaced by `rules`.
pub loaders: Option<JsonValue>,
pub rules: Option<IndexMap<String, RuleConfigItem>>,
pub rules: Option<IndexMap<String, RuleConfigItemOrShortcut>>,
pub resolve_alias: Option<IndexMap<String, JsonValue>>,
pub resolve_extensions: Option<Vec<String>>,
pub use_swc_css: Option<bool>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
#[serde(rename_all = "camelCase")]
pub struct RuleConfigItemOptions {
pub loaders: Vec<LoaderItem>,
#[serde(default, alias = "as")]
pub rename_as: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
#[serde(rename_all = "camelCase", untagged)]
pub enum RuleConfigItem {
pub enum RuleConfigItemOrShortcut {
Loaders(Vec<LoaderItem>),
Options {
loaders: Vec<LoaderItem>,
#[serde(default, alias = "as")]
rename_as: Option<String>,
},
Advanced(RuleConfigItem),
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
#[serde(rename_all = "camelCase", untagged)]
pub enum RuleConfigItem {
Options(RuleConfigItemOptions),
Conditional(IndexMap<String, RuleConfigItem>),
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TraceRawVcs)]
Expand Down Expand Up @@ -691,7 +704,10 @@ impl NextConfig {
}

#[turbo_tasks::function]
pub async fn webpack_rules(self: Vc<Self>) -> Result<Vc<OptionWebpackRules>> {
pub async fn webpack_rules(
self: Vc<Self>,
active_conditions: Vec<String>,
) -> Result<Vc<OptionWebpackRules>> {
let this = self.await?;
let Some(turbo_rules) = this
.experimental
Expand All @@ -704,8 +720,9 @@ impl NextConfig {
if turbo_rules.is_empty() {
return Ok(Vc::cell(None));
}
let active_conditions = active_conditions.into_iter().collect::<HashSet<_>>();
let mut rules = IndexMap::new();
for (ext, rule) in turbo_rules {
for (ext, rule) in turbo_rules.iter() {
fn transform_loaders(loaders: &[LoaderItem]) -> Vc<WebpackLoaderItems> {
Vc::cell(
loaders
Expand All @@ -720,18 +737,50 @@ impl NextConfig {
.collect(),
)
}
let rule = match rule {
RuleConfigItem::Loaders(loaders) => LoaderRuleItem {
loaders: transform_loaders(loaders),
rename_as: None,
},
RuleConfigItem::Options { loaders, rename_as } => LoaderRuleItem {
loaders: transform_loaders(loaders),
rename_as: rename_as.clone(),
},
};

rules.insert(ext.clone(), rule);
fn find_rule<'a>(
rule: &'a RuleConfigItem,
active_conditions: &HashSet<String>,
) -> Option<&'a RuleConfigItemOptions> {
match rule {
RuleConfigItem::Options(rule) => {
return Some(rule);
}
RuleConfigItem::Conditional(map) => {
for (condition, rule) in map.iter() {
if condition == "default" || active_conditions.contains(condition) {
if let Some(rule) = find_rule(rule, active_conditions) {
return Some(rule);
}
}
}
}
}
None
}
match rule {
RuleConfigItemOrShortcut::Loaders(loaders) => {
rules.insert(
ext.to_string(),
LoaderRuleItem {
loaders: transform_loaders(loaders),
rename_as: None,
},
);
}
RuleConfigItemOrShortcut::Advanced(rule) => {
if let Some(RuleConfigItemOptions { loaders, rename_as }) =
find_rule(rule, &active_conditions)
{
rules.insert(
ext.to_string(),
LoaderRuleItem {
loaders: transform_loaders(loaders),
rename_as: rename_as.clone(),
},
);
}
}
}
}
Ok(Vc::cell(Some(Vc::cell(rules))))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub async fn get_edge_resolve_options_context(

// https://github.com/vercel/next.js/blob/bf52c254973d99fed9d71507a2e818af80b8ade7/packages/next/src/build/webpack-config.ts#L96-L102
let mut custom_conditions = vec![
mode.await?.node_env().to_string(),
mode.await?.condition().to_string(),
"edge-light".to_string(),
"worker".to_string(),
];
Expand Down
Loading

0 comments on commit 97a8e66

Please sign in to comment.