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

feat: hot-update 文件生成放到 node_modules 下 #424

Closed
wants to merge 20 commits into from
Closed
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
57 changes: 53 additions & 4 deletions crates/mako/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use futures::{SinkExt, StreamExt};
use hyper::header::CONTENT_TYPE;
use hyper::http::HeaderValue;
use hyper::Server;
use regex::Regex;
use tokio::sync::broadcast::{Receiver, Sender};
use tokio::task::JoinHandle;
use tokio::try_join;
Expand Down Expand Up @@ -70,7 +71,7 @@ impl DevServer {
}
let arc_watcher = self.watcher.clone();
let compiler = self.compiler.clone();
let handle_request = move |req: hyper::Request<hyper::Body>| {
let handle_request = move |mut req: hyper::Request<hyper::Body>| {
let for_fn = compiler.clone();
let w = arc_watcher.clone();
async move {
Expand All @@ -79,6 +80,15 @@ impl DevServer {
let static_serve =
hyper_staticfile::Static::new(for_fn.context.config.output.path.clone());

let static_serve_hmr = hyper_staticfile::Static::new(
for_fn.context.root.join("node_modules/.mako/hot_update"),
);

// 去除 publicPath 头尾 /
let public_path = for_fn.context.config.public_path.clone();
let public_path_without_fix =
public_path.trim_start_matches('/').trim_end_matches('/');

match path {
"__/hmr-ws" => {
if hyper_tungstenite::is_upgrade_request(&req) {
Expand All @@ -102,9 +112,42 @@ impl DevServer {
)
}
}
_ => {
// try chunk content in memory first, else use dist content
match static_serve.serve(req).await {
_ if path.starts_with(public_path_without_fix) => {
// 如果用户设置了 public_path,修改一下原始 req,手动复制 req 担心掉属性
if !public_path.is_empty() {
let public_path_re = Regex::new(public_path_without_fix).unwrap();
let uri_str = public_path_re
.replacen(req.uri().to_string().as_str(), 1, "")
.to_string();
let uri_cloned = uri_str.as_str().parse::<hyper::Uri>().unwrap();
*req.uri_mut() = uri_cloned;
};

// clone 一份 req,用于做 hmr 的匹配
let herders_cloned = req.headers().clone();
let uri_cloned = req.uri().clone();
let mut req_cloned = hyper::Request::builder()
.method(hyper::Method::GET)
.uri(uri_cloned)
.body(hyper::Body::empty())
.unwrap();
req_cloned.headers_mut().extend(herders_cloned);

// 先匹配 hmr 请求静态资源请求,用复制的 req
let static_serve_hmr_result = static_serve_hmr.serve(req_cloned).await;
let serve_result = match static_serve_hmr_result {
Ok(res) => {
if res.status() == hyper::StatusCode::OK {
Ok(res)
} else {
static_serve.serve(req).await
}
}
_ => static_serve.serve(req).await,
};

// 后续处理
match serve_result {
Ok(mut res) => {
if let Some(content_type) = res.headers().get(CONTENT_TYPE).cloned()
{
Expand Down Expand Up @@ -132,6 +175,12 @@ impl DevServer {
),
}
}
_ => Ok::<_, hyper::Error>(
hyper::Response::builder()
.status(hyper::StatusCode::NOT_FOUND)
.body(hyper::Body::from("404 - Page not found"))
.unwrap(),
),
}
}
};
Expand Down
27 changes: 20 additions & 7 deletions crates/mako/src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,13 @@ impl Compiler {
let (code, sourcemap) =
self.generate_hmr_chunk(chunk, &filename, &modified_ids, current_full_hash)?;
// TODO the final format should be {name}.{full_hash}.hot-update.{ext}
self.write_to_dist(&filename, code);
self.write_to_dist(format!("{}.map", &filename), sourcemap);
self.write_to_hot_update_dir(&filename, code);
self.write_to_hot_update_dir(format!("{}.map", &filename), sourcemap);
}
}
let t_generate_hmr_chunk = t_generate_hmr_chunk.elapsed();

self.write_to_dist(
self.write_to_hot_update_dir(
format!("{}.hot-update.json", last_full_hash),
serde_json::to_string(&HotUpdateManifest {
removed_chunks,
Expand Down Expand Up @@ -372,15 +372,28 @@ impl Compiler {
Ok(current_full_hash)
}

pub fn write_to_dist<P: AsRef<std::path::Path>, C: AsRef<[u8]>>(
// pub fn write_to_dist<P: AsRef<std::path::Path>, C: AsRef<[u8]>>(
// &self,
// filename: P,
// content: C,
// ) {
// let to = self.context.config.output.path.join(filename);

// std::fs::write(to, content).unwrap();
// }

pub fn write_to_hot_update_dir<P: AsRef<std::path::Path>, C: AsRef<[u8]>>(
&self,
filename: P,
content: C,
) {
let to = self.context.config.output.path.join(filename);

std::fs::write(to, content).unwrap();
let hmr_dir = self.context.root.join("node_modules/.mako/hot_update");
Copy link
Member

Choose a reason for hiding this comment

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

这里用 node_modules/.mako,是不是 runtime 就不需要调整了,改动可以小一点。

Copy link
Contributor Author

Choose a reason for hiding this comment

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

好像是可以的,我再调整下

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • 如果用 node_modules/.mako,runtime 还是需要改的:不放到 output 目录下了,得把 requireModule.publicPath 去掉。
  • 我这里还是保留 /hot_update 呢,感觉语义更清晰些

if !hmr_dir.exists() {
fs::create_dir_all(&hmr_dir).unwrap();
}
std::fs::write(hmr_dir.join(filename), content).unwrap();
}

// 写入产物前记录 content 大小, 并加上 hash 值
pub fn write_to_dist_with_stats(&self, file: EmitFile) {
let to: PathBuf = self.context.config.output.path.join(file.hashname.clone());
Expand Down
1 change: 0 additions & 1 deletion crates/mako/src/runtime/runtime_entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ function createRuntime(makoModules, entryModuleId) {
invalidate() {},
check() {
const current_hash = requireModule.currentHash();

return fetch(
`${requireModule.publicPath}${current_hash}.hot-update.json`,
)
Expand Down
6 changes: 5 additions & 1 deletion crates/node/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ alias?: Record<string, string>;
extensions?: string[];
};
manifest?: boolean;
manifest_config?: {file_name: string; base_path: string;};
manifest_config?: {
file_name: string;
base_path: string;
};
mode?: "development" | "production";
define?: Record<string, string>;
devtool?: "source-map" | "inline-source-map" | "none";
externals?: Record<string, string>;
copy?: string[];
code_splitting: "bigVendors" | "depPerChunk" | "none";
providers?: Record<string, string[]>;
public_path?: string;
inline_limit?: number;
Expand Down
2 changes: 1 addition & 1 deletion examples/with-dynamic-import/mako.config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"public_path": "/",
"publicPath": "/",
"codeSplitting": "none"
}
11 changes: 9 additions & 2 deletions packages/bundler-okam/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,15 @@ exports.dev = async function (opts) {
}
// before middlewares
(opts.beforeMiddlewares || []).forEach((m) => app.use(m));

// 暂时无法读到 mako.config 里的 publicPath
const publicPath = opts.config.publicPath || '/';
// serve dist files
app.use(express.static(path.join(opts.cwd, 'dist')));
app.use(
publicPath,
express.static(path.join(opts.cwd, 'node_modules/.mako/hot_update')),
);
app.use(publicPath, express.static(path.join(opts.cwd, 'dist')));
// TODO: proxy
// opts.config.proxy
// after middlewares
Expand Down Expand Up @@ -155,7 +162,7 @@ function getOkamConfig(opts) {
},
},
mode: 'development',
public_path: runtimePublicPath ? 'runtime' : publicPath || '/',
publicPath: runtimePublicPath ? 'runtime' : publicPath || '/',
targets: targets || {
chrome: 80,
},
Expand Down