Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add experimental option to use sass-loader@16 #72423

Draft
wants to merge 19 commits into
base: canary
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@
"RUST_BACKTRACE": "0"
},
"cSpell.words": [
"codemod",
"codemods",
"Destructuring",
"buildtime",
"callsites",
"codemod",
"codemods",
"datastream",
"deduped",
"Destructuring",
"draftmode",
"Entrypoints",
"jiwon",
"jscodeshift",
"napi",
"navigations",
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/next-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ tracing = { workspace = true }
rustc-hash = { workspace = true }
react_remove_properties = "0.24.25"
remove_console = "0.25.25"
semver = { workspace = true }

auto-hash-map = { workspace = true }

Expand Down Expand Up @@ -76,6 +77,7 @@ turbopack-nodejs = { workspace = true }
turbopack-static = { workspace = true }
turbopack-trace-server = { workspace = true }
turbopack-trace-utils = { workspace = true }
turbopack-resolve = { workspace = true }

[build-dependencies]
turbo-tasks-build = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/next-core/src/next_shared/webpack_rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
conditions: Vec<RcStr>,
) -> Result<Option<ResolvedVc<WebpackLoadersOptions>>> {
let rules = *next_config.webpack_rules(conditions).await?;
let rules = *maybe_add_sass_loader(next_config.sass_config(), rules.map(|v| *v)).await?;
let rules = *maybe_add_sass_loader(next_config.sass_config(), rules.map(|v| *v), project_path).await?;

Check failure on line 20 in crates/next-core/src/next_shared/webpack_rules/mod.rs

View workflow job for this annotation

GitHub Actions / stable - x86_64-unknown-linux-gnu - node@16

mismatched types
let rules = if foreign {
rules
} else {
Expand Down
60 changes: 56 additions & 4 deletions crates/next-core/src/next_shared/webpack_rules/sass.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,76 @@
use std::mem::take;
use std::{io::Read, mem::take};

use anyhow::{bail, Result};
use semver::Version;
use serde_json::Value as JsonValue;
use turbo_tasks::{ResolvedVc, Vc};
use turbo_tasks_fs::{FileContent, FileSystemPath};
use turbopack::module_options::{LoaderRuleItem, OptionWebpackRules, WebpackRules};
use turbopack_core::{
asset::{Asset, AssetContent},
resolve::{pattern::Pattern, resolve_raw},
};
use turbopack_node::transforms::webpack::WebpackLoaderItem;

#[turbo_tasks::function]
pub async fn maybe_add_sass_loader(
sass_options: Vc<JsonValue>,
webpack_rules: Option<Vc<WebpackRules>>,
package_dir: Vc<FileSystemPath>,
) -> Result<Vc<OptionWebpackRules>> {
let sass_options = sass_options.await?;
let Some(mut sass_options) = sass_options.as_object().cloned() else {
bail!("sass_options must be an object");
};
// TODO: Remove this once we upgrade to sass-loader 16

let sass_package_json_path = resolve_raw(
package_dir,
Pattern::Constant("sass/package.json".into()).cell(),
false,
)
.first_source()
.await?;

let sass_version = match &*sass_package_json_path {
Some(sass_package_json) => {
let sass_package_json_content = sass_package_json.content().await?;
match &*sass_package_json_content {
AssetContent::File(file_content) => match &*file_content.await? {
FileContent::Content(file) => {
let mut reader = file.read();
let mut buf = Vec::new();
reader.read_to_end(&mut buf)?;
let json_value = serde_json::from_slice::<serde_json::Value>(&buf)?;
json_value
.get("version")
.unwrap()
.as_str()
.map(Version::parse)
}
_ => None,
},
_ => None,
}
}
None => None,
}
.transpose()?
.unwrap_or_else(|| Version::new(1, 45, 0));

// The modern Sass API with breaking changes was added in [email protected].
// https://sass-lang.com/documentation/breaking-changes/legacy-js-api
// Since sass-loader and our peer dependency sass version is ^1.3.0,
// we need to use the legacy Sass API for versions less than 1.45.0.
let should_use_legacy_sass_api = sass_version < Version::parse("1.45.0")?;

// TODO(jiwon): Once the peer dependency for sass is upgraded to >= 1.45.0, we can remove this.
sass_options.insert(
"silenceDeprecations".into(),
serde_json::json!(["legacy-js-api"]),
"api".into(),
serde_json::json!(if should_use_legacy_sass_api {
"legacy"
} else {
"modern"
}),
);
let mut rules = if let Some(webpack_rules) = webpack_rules {
webpack_rules.await?.clone_value()
Expand Down
2 changes: 1 addition & 1 deletion packages/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@
"raw-body": "2.4.1",
"react-refresh": "0.12.0",
"regenerator-runtime": "0.13.4",
"sass-loader": "15.0.0",
"sass-loader": "16.0.0",
"schema-utils2": "npm:[email protected]",
"schema-utils3": "npm:[email protected]",
"semver": "7.3.2",
Expand Down
17 changes: 15 additions & 2 deletions packages/next/src/build/webpack/config/blocks/css/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import curry from 'next/dist/compiled/lodash.curry'
import type { webpack } from 'next/dist/compiled/webpack/webpack'
import { lt as semverLessThan } from 'next/dist/compiled/semver'
import { loader, plugin } from '../../helpers'
import { pipe } from '../../utils'
import type { ConfigurationContext, ConfigurationFn } from '../../utils'
Expand Down Expand Up @@ -162,6 +163,18 @@ export const css = curry(async function css(
ctx.experimental.useLightningcss
)

// Since sass is an optional peer dependency, it may be missing.
let sassVersion = ''
devjiwonchoi marked this conversation as resolved.
Show resolved Hide resolved
try {
sassVersion = require(require.resolve('sass/package.json')).version
} catch {}

// The modern Sass API with breaking changes was added in [email protected].
// https://sass-lang.com/documentation/breaking-changes/legacy-js-api
// Since sass-loader and our peer dependency sass version is ^1.3.0,
// we need to use the legacy Sass API for versions less than 1.45.0.
const shouldUseLegacySassAPI = semverLessThan(sassVersion, '1.45.0')

const sassPreprocessors: webpack.RuleSetUseItem[] = [
// First, process files with `sass-loader`: this inlines content, and
// compiles away the proprietary syntax.
Expand All @@ -181,8 +194,8 @@ export const css = curry(async function css(
// Since it's optional and not required, we'll disable it by default
// to avoid the confusion.
fibers: false,
// TODO: Remove this once we upgrade to sass-loader 16
silenceDeprecations: ['legacy-js-api'],
// TODO(jiwon): Once the peer dependency for sass is upgraded to >= 1.45.0, we can remove this.
api: shouldUseLegacySassAPI ? 'legacy' : 'modern',
...sassOptions,
},
additionalData: sassPrependData || sassAdditionalData,
Expand Down
Loading
Loading