Skip to content
New issue

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

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

Already on GitHub? # to your account

perf: reuse compiler process when using sass-embedded #1195

Merged
Changes from all 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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -657,12 +657,12 @@ module.exports = {
Type:

```ts
type api = "legacy" | "modern";
type api = "legacy" | "modern" | "modern-compiler";
```

Default: `"legacy"`

Allows you to switch between `legacy` and `modern` API. You can find more information [here](https://sass-lang.com/documentation/js-api).
Allows you to switch between `legacy` and `modern` API. You can find more information [here](https://sass-lang.com/documentation/js-api). The `modern-compiler` option enables the modern API with support for [Shared Resources](https://github.com/sass/sass/blob/main/accepted/shared-resources.d.ts.md).

> **Warning**
>
7 changes: 4 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -47,7 +47,8 @@ async function loader(content) {
: true;

if (shouldUseWebpackImporter) {
const isModernAPI = options.api === "modern";
const isModernAPI =
options.api === "modern" || options.api === "modern-compiler";

if (!isModernAPI) {
const { includePaths } = sassOptions;
@@ -65,7 +66,7 @@ async function loader(content) {
let compile;

try {
compile = getCompileFn(implementation, options);
compile = getCompileFn(this, implementation, options);
} catch (error) {
callback(error);
return;
@@ -74,7 +75,7 @@ async function loader(content) {
let result;

try {
result = await compile(sassOptions, options);
result = await compile(sassOptions);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed unused argument.

} catch (error) {
// There are situations when the `file`/`span.url` property do not exist
// Modern API
2 changes: 1 addition & 1 deletion src/options.json
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
"api": {
"description": "Switch between old and modern API for `sass` (`Dart Sass`) and `Sass Embedded` implementations.",
"link": "https://github.com/webpack-contrib/sass-loader#sassoptions",
"enum": ["legacy", "modern"]
"enum": ["legacy", "modern", "modern-compiler"]
},
"sassOptions": {
"description": "Options for `node-sass` or `sass` (`Dart Sass`) implementation.",
40 changes: 37 additions & 3 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -174,7 +174,8 @@
};
}

const isModernAPI = loaderOptions.api === "modern";
const isModernAPI =
loaderOptions.api === "modern" || loaderOptions.api === "modern-compiler";
const { resourcePath } = loaderContext;

if (isModernAPI) {
@@ -650,15 +651,17 @@
}

let nodeSassJobQueue = null;
const sassModernCompilers = new WeakMap();

/**
* Verifies that the implementation and version of Sass is supported by this loader.
*
* @param {Object} loaderContext
* @param {Object} implementation
* @param {Object} options
* @returns {Function}
*/
function getCompileFn(implementation, options) {
function getCompileFn(loaderContext, implementation, options) {
const isNewSass =
implementation.info.includes("dart-sass") ||
implementation.info.includes("sass-embedded");
@@ -672,6 +675,37 @@
};
}

if (options.api === "modern-compiler") {
return async (sassOptions) => {
// eslint-disable-next-line no-underscore-dangle
const webpackCompiler = loaderContext._compiler;
const { data, ...rest } = sassOptions;

// Some people can run the loader in a multi-threading way;
// there is no webpack compiler object in such case.
if (webpackCompiler) {
if (!sassModernCompilers.has(implementation)) {
// Create a long-running compiler process that can be reused
// for compiling individual files.
const compiler = await implementation.initAsyncCompiler();
// Check again because awaiting the initialization function
// introduces a race condition.
if (!sassModernCompilers.has(implementation)) {
sassModernCompilers.set(implementation, compiler);
webpackCompiler.hooks.shutdown.tap("sass-loader", () => {
compiler.dispose();

Check warning on line 696 in src/utils.js

Codecov / codecov/patch

src/utils.js#L696

Added line #L696 was not covered by tests
});
}
}
return sassModernCompilers
.get(implementation)
.compileStringAsync(data, rest);
}

return implementation.compileStringAsync(data, rest);

Check warning on line 705 in src/utils.js

Codecov / codecov/patch

src/utils.js#L705

Added line #L705 was not covered by tests
};
}

return (sassOptions) =>
new Promise((resolve, reject) => {
implementation.render(sassOptions, (error, result) => {
@@ -686,7 +720,7 @@
});
}

if (options.api === "modern") {
if (options.api === "modern" || options.api === "modern-compiler") {
throw new Error("Modern API is not supported for 'node-sass'");
}

176 changes: 176 additions & 0 deletions test/__snapshots__/additionalData-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -56,6 +56,34 @@ exports[`additionalData option should use same EOL on all os ('dart-sass', 'mode

exports[`additionalData option should use same EOL on all os ('dart-sass', 'modern' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('dart-sass', 'modern-compiler' API, 'sass' syntax): css 1`] = `
"a {
color: hotpink;
}

body {
color: hotpink;
}"
`;

exports[`additionalData option should use same EOL on all os ('dart-sass', 'modern-compiler' API, 'sass' syntax): errors 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('dart-sass', 'modern-compiler' API, 'sass' syntax): warnings 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('dart-sass', 'modern-compiler' API, 'scss' syntax): css 1`] = `
"a {
color: red;
}

body {
color: hotpink;
}"
`;

exports[`additionalData option should use same EOL on all os ('dart-sass', 'modern-compiler' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('dart-sass', 'modern-compiler' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('node-sass', 'legacy' API, 'sass' syntax): css 1`] = `
"a {
color: hotpink; }
@@ -138,6 +166,34 @@ exports[`additionalData option should use same EOL on all os ('sass-embedded', '

exports[`additionalData option should use same EOL on all os ('sass-embedded', 'modern' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('sass-embedded', 'modern-compiler' API, 'sass' syntax): css 1`] = `
"a {
color: hotpink;
}

body {
color: hotpink;
}"
`;

exports[`additionalData option should use same EOL on all os ('sass-embedded', 'modern-compiler' API, 'sass' syntax): errors 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('sass-embedded', 'modern-compiler' API, 'sass' syntax): warnings 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('sass-embedded', 'modern-compiler' API, 'scss' syntax): css 1`] = `
"a {
color: red;
}

body {
color: hotpink;
}"
`;

exports[`additionalData option should use same EOL on all os ('sass-embedded', 'modern-compiler' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should use same EOL on all os ('sass-embedded', 'modern-compiler' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a function ('dart-sass', 'legacy' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
@@ -178,6 +234,26 @@ exports[`additionalData option should work as a function ('dart-sass', 'modern'

exports[`additionalData option should work as a function ('dart-sass', 'modern' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a function ('dart-sass', 'modern-compiler' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as a function ('dart-sass', 'modern-compiler' API, 'sass' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as a function ('dart-sass', 'modern-compiler' API, 'sass' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a function ('dart-sass', 'modern-compiler' API, 'scss' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as a function ('dart-sass', 'modern-compiler' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as a function ('dart-sass', 'modern-compiler' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a function ('node-sass', 'legacy' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink; }
@@ -238,6 +314,26 @@ exports[`additionalData option should work as a function ('sass-embedded', 'mode

exports[`additionalData option should work as a function ('sass-embedded', 'modern' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a function ('sass-embedded', 'modern-compiler' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as a function ('sass-embedded', 'modern-compiler' API, 'sass' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as a function ('sass-embedded', 'modern-compiler' API, 'sass' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a function ('sass-embedded', 'modern-compiler' API, 'scss' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as a function ('sass-embedded', 'modern-compiler' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as a function ('sass-embedded', 'modern-compiler' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a string ('dart-sass', 'legacy' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
@@ -278,6 +374,26 @@ exports[`additionalData option should work as a string ('dart-sass', 'modern' AP

exports[`additionalData option should work as a string ('dart-sass', 'modern' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a string ('dart-sass', 'modern-compiler' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as a string ('dart-sass', 'modern-compiler' API, 'sass' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as a string ('dart-sass', 'modern-compiler' API, 'sass' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a string ('dart-sass', 'modern-compiler' API, 'scss' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as a string ('dart-sass', 'modern-compiler' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as a string ('dart-sass', 'modern-compiler' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a string ('node-sass', 'legacy' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink; }
@@ -338,6 +454,26 @@ exports[`additionalData option should work as a string ('sass-embedded', 'modern

exports[`additionalData option should work as a string ('sass-embedded', 'modern' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a string ('sass-embedded', 'modern-compiler' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as a string ('sass-embedded', 'modern-compiler' API, 'sass' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as a string ('sass-embedded', 'modern-compiler' API, 'sass' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as a string ('sass-embedded', 'modern-compiler' API, 'scss' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as a string ('sass-embedded', 'modern-compiler' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as a string ('sass-embedded', 'modern-compiler' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as an async function ('dart-sass', 'legacy' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
@@ -378,6 +514,26 @@ exports[`additionalData option should work as an async function ('dart-sass', 'm

exports[`additionalData option should work as an async function ('dart-sass', 'modern' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as an async function ('dart-sass', 'modern-compiler' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as an async function ('dart-sass', 'modern-compiler' API, 'sass' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as an async function ('dart-sass', 'modern-compiler' API, 'sass' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as an async function ('dart-sass', 'modern-compiler' API, 'scss' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as an async function ('dart-sass', 'modern-compiler' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as an async function ('dart-sass', 'modern-compiler' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as an async function ('node-sass', 'legacy' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink; }
@@ -437,3 +593,23 @@ exports[`additionalData option should work as an async function ('sass-embedded'
exports[`additionalData option should work as an async function ('sass-embedded', 'modern' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as an async function ('sass-embedded', 'modern' API, 'scss' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as an async function ('sass-embedded', 'modern-compiler' API, 'sass' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as an async function ('sass-embedded', 'modern-compiler' API, 'sass' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as an async function ('sass-embedded', 'modern-compiler' API, 'sass' syntax): warnings 1`] = `[]`;

exports[`additionalData option should work as an async function ('sass-embedded', 'modern-compiler' API, 'scss' syntax): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work as an async function ('sass-embedded', 'modern-compiler' API, 'scss' syntax): errors 1`] = `[]`;

exports[`additionalData option should work as an async function ('sass-embedded', 'modern-compiler' API, 'scss' syntax): warnings 1`] = `[]`;
Loading
Loading