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

fix: css runtime should have hmr handler when lazy-compilation #8400

Merged
merged 1 commit into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions crates/rspack_core/src/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,13 +1408,18 @@ impl Compilation {
let mut runtime_requirements;

loop {
// runtime_requirements: rt_requirements of last time
// runtime_requirements_mut: changed rt_requirements
// requirements: all rt_requirements
runtime_requirements = runtime_requirements_mut;
runtime_requirements_mut = RuntimeGlobals::default();
call_hook(
requirements,
&runtime_requirements,
&mut runtime_requirements_mut,
)?;

// check if we have changes to runtime_requirements
runtime_requirements_mut =
runtime_requirements_mut.difference(requirements.intersection(runtime_requirements_mut));
if runtime_requirements_mut.is_empty() {
Expand Down Expand Up @@ -1891,6 +1896,7 @@ impl Compilation {
let runtime_module_identifier =
ModuleIdentifier::from(format!("{}/{}", &chunk.runtime, module.identifier()));
module.attach(*chunk_ukey);

self.chunk_graph.add_module(runtime_module_identifier);
self
.chunk_graph
Expand Down
34 changes: 13 additions & 21 deletions crates/rspack_plugin_extract_css/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,35 +432,29 @@ async fn compilation(
}

#[plugin_hook(CompilationRuntimeRequirementInTree for PluginCssExtract)]
fn runtime_requirements_in_tree(
fn runtime_requirement_in_tree(
&self,
compilation: &mut Compilation,
chunk_ukey: &ChunkUkey,
_all_runtime_requirements: &RuntimeGlobals,
runtime_requirements: &RuntimeGlobals,
runtime_requirements_mut: &mut RuntimeGlobals,
) -> Result<Option<()>> {
// different from webpack, Rspack can invoke this multiple times,
// each time with current runtime_globals, and records every mutation
// by `runtime_requirements_mut`, but this RuntimeModule depends on
// 2 runtimeGlobals, if check current runtime_requirements, we might
// insert CssLoadingRuntimeModule with with_loading: true but with_hmr: false
// for the first time, and with_loading: false but with_hmr: true for the
// second time
// For plugin that depends on 2 runtime_globals, should check all_runtime_requirements
if !self.options.runtime {
return Ok(None);
}

let with_loading = runtime_requirements.contains(RuntimeGlobals::ENSURE_CHUNK_HANDLERS) && {
let chunk = compilation.chunk_by_ukey.expect_get(chunk_ukey);

chunk
.get_all_async_chunks(&compilation.chunk_group_by_ukey)
.iter()
.any(|chunk| {
!compilation
.chunk_graph
.get_chunk_modules_by_source_type(chunk, SOURCE_TYPE[0], &compilation.get_module_graph())
.is_empty()
})
};

let with_hmr = runtime_requirements.contains(RuntimeGlobals::HMR_DOWNLOAD_UPDATE_HANDLERS);

if with_loading || with_hmr {
if runtime_requirements.contains(RuntimeGlobals::HMR_DOWNLOAD_UPDATE_HANDLERS)
|| runtime_requirements.contains(RuntimeGlobals::ENSURE_CHUNK_HANDLERS)
{
if let Some(chunk_filename) = self.options.chunk_filename.template()
&& chunk_filename.contains("hash")
{
Expand Down Expand Up @@ -499,8 +493,6 @@ fn runtime_requirements_in_tree(
self.options.attributes.clone(),
self.options.link_type.clone(),
self.options.insert.clone(),
with_loading,
with_hmr,
)),
)?;
}
Expand Down Expand Up @@ -668,7 +660,7 @@ impl Plugin for PluginCssExtract {
.context
.compilation_hooks
.runtime_requirement_in_tree
.tap(runtime_requirements_in_tree::new(self));
.tap(runtime_requirement_in_tree::new(self));
ctx
.context
.compilation_hooks
Expand Down
44 changes: 33 additions & 11 deletions crates/rspack_plugin_extract_css/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ use std::sync::Arc;
use cow_utils::CowUtils;
use rspack_collections::UkeySet;
use rspack_core::{
impl_runtime_module, rspack_sources::RawSource, ChunkUkey, Compilation, CrossOriginLoading,
RuntimeGlobals, RuntimeModule, RuntimeModuleStage,
impl_runtime_module,
rspack_sources::{RawSource, SourceExt},
ChunkUkey, Compilation, CrossOriginLoading, RuntimeGlobals, RuntimeModule, RuntimeModuleStage,
};
use rspack_error::Result;
use rspack_plugin_runtime::get_chunk_runtime_requirements;
use rustc_hash::FxHashMap;

use crate::plugin::{InsertType, SOURCE_TYPE};
Expand All @@ -22,9 +24,6 @@ pub(crate) struct CssLoadingRuntimeModule {
attributes: FxHashMap<String, String>,
link_type: Option<String>,
insert: InsertType,

loading: bool,
hmr: bool,
}

impl CssLoadingRuntimeModule {
Expand All @@ -33,10 +32,8 @@ impl CssLoadingRuntimeModule {
attributes: FxHashMap<String, String>,
link_type: Option<String>,
insert: InsertType,
loading: bool,
hmr: bool,
) -> Self {
Self::with_default(chunk, attributes, link_type, insert, loading, hmr)
Self::with_default(chunk, attributes, link_type, insert)
}

fn get_css_chunks(&self, compilation: &Compilation) -> UkeySet<ChunkUkey> {
Expand Down Expand Up @@ -73,9 +70,34 @@ impl RuntimeModule for CssLoadingRuntimeModule {
compilation: &rspack_core::Compilation,
) -> Result<rspack_core::rspack_sources::BoxSource> {
let runtime = RUNTIME_CODE;
let runtime_requirements = get_chunk_runtime_requirements(compilation, &self.chunk);

let with_loading = runtime_requirements.contains(RuntimeGlobals::ENSURE_CHUNK_HANDLERS) && {
let chunk = compilation.chunk_by_ukey.expect_get(&self.chunk);

chunk
.get_all_async_chunks(&compilation.chunk_group_by_ukey)
.iter()
.any(|chunk| {
!compilation
.chunk_graph
.get_chunk_modules_by_source_type(
chunk,
SOURCE_TYPE[0],
&compilation.get_module_graph(),
)
.is_empty()
})
};

let with_hmr = runtime_requirements.contains(RuntimeGlobals::HMR_DOWNLOAD_UPDATE_HANDLERS);

if !with_hmr && !with_loading {
return Ok(RawSource::from("").boxed());
}

let mut attr = String::default();
let mut attributes = self.attributes.iter().collect::<Vec<_>>();
let mut attributes: Vec<(&String, &String)> = self.attributes.iter().collect::<Vec<_>>();
attributes.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2));

for (attr_key, attr_value) in attributes {
Expand Down Expand Up @@ -121,7 +143,7 @@ impl RuntimeModule for CssLoadingRuntimeModule {
),
};

let runtime = if self.loading {
let runtime = if with_loading {
let chunks = self.get_css_chunks(compilation);
if chunks.is_empty() {
runtime.cow_replace("__WITH_LOADING__", "// no chunk loading")
Expand Down Expand Up @@ -171,7 +193,7 @@ impl RuntimeModule for CssLoadingRuntimeModule {
runtime.cow_replace("__WITH_LOADING__", "// no chunk loading")
};

let runtime = if self.hmr {
let runtime = if with_hmr {
runtime.cow_replace(
"__WITH_HMT__",
&WITH_HMR.cow_replace(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { expect, test } from "@/fixtures";

test("should update style", async ({ page }) => {
const body = await page.$("body");
const backgroundColor = await body!.evaluate(
el => window.getComputedStyle(el).backgroundColor
);
// first time enter the page, style is red
expect(backgroundColor, "red");

// second time enter the page, this time brings query,
// trigger lazy-compile
const url = await body!.evaluate(() => window.location.href);
await page.goto(`${url}?1`);
const updatedBody = await page.$("body");
const updatedBackgroundColor = await updatedBody!.evaluate(
el => window.getComputedStyle(el).backgroundColor
);
// first time enter the page, style is red
expect(updatedBackgroundColor, "blue");
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const rspack = require("@rspack/core");

/** @type { import('@rspack/core').RspackOptions } */
module.exports = {
context: __dirname,
entry: "./src/index.js",
mode: "development",
module: {
rules: [
{
test: /\.css$/,
use: [rspack.CssExtractRspackPlugin.loader, "css-loader"]
}
]
},
plugins: [new rspack.HtmlRspackPlugin(), new rspack.CssExtractRspackPlugin()],
experiments: {
css: false,
lazyCompilation: true
},
optimization: {
splitChunks: {
minSize: 0,
chunks: "all",
cacheGroups: {
styles: {
test: /\.css$/,
name: "style.css"
}
}
}
},
devServer: {
hot: true,
port: 5678
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
background-color: blue;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "./blue.css";
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import "./red.css";

if (new URL(window.location.href).search) {
// @ts-expect-error change.js no dts
import("./change.js");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
body {
background-color: red;
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ __webpack_require__.e = function (chunkId) {
return "" + chunkId + ".js";
};

})();
// webpack/runtime/get mini-css chunk filename
(() => {
// This function allow to reference chunks
__webpack_require__.miniCssF = function (chunkId) {
// return url for filenames not based on template

// return url for filenames based on template
return "" + chunkId + ".css";
};

})();
// webpack/runtime/global
(() => {
Expand Down
Loading