From ce9ad87aadcee4e9406b128e139b0840c56ac458 Mon Sep 17 00:00:00 2001 From: xusd320 Date: Tue, 10 Dec 2024 15:47:36 +0800 Subject: [PATCH] feat: supports publicPath: auto --- crates/mako/src/config.rs | 4 +- crates/mako/src/plugins/runtime.rs | 48 ++++++++++++++----- docs/config.md | 6 ++- docs/config.zh-CN.md | 4 +- .../config.public_path.auto/expect.js | 11 +++++ .../config.public_path.auto/mako.config.json | 3 ++ .../config.public_path.auto/src/index.tsx | 1 + 7 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 e2e/fixtures/config.public_path.auto/expect.js create mode 100644 e2e/fixtures/config.public_path.auto/mako.config.json create mode 100644 e2e/fixtures/config.public_path.auto/src/index.tsx diff --git a/crates/mako/src/config.rs b/crates/mako/src/config.rs index 1dbc8c3ef..1cbb58574 100644 --- a/crates/mako/src/config.rs +++ b/crates/mako/src/config.rs @@ -306,7 +306,9 @@ impl Config { .define .insert("NODE_ENV".to_string(), serde_json::Value::String(mode)); - if config.public_path != "runtime" && !config.public_path.ends_with('/') { + if ["runtime", "auto"].iter().all(|p| *p != config.public_path) + && !config.public_path.ends_with('/') + { return Err(anyhow!("public_path must end with '/' or be 'runtime'")); } diff --git a/crates/mako/src/plugins/runtime.rs b/crates/mako/src/plugins/runtime.rs index 77828ae9c..dedd7d18a 100644 --- a/crates/mako/src/plugins/runtime.rs +++ b/crates/mako/src/plugins/runtime.rs @@ -26,20 +26,46 @@ impl Plugin for MakoRuntime { impl MakoRuntime { fn public_path(&self, context: &Arc) -> String { let public_path = context.config.public_path.clone(); - let public_path = if public_path == "runtime" { - "(typeof globalThis !== 'undefined' ? globalThis : self).publicPath || '/'".to_string() - } else { - format!("\"{}\"", public_path) - }; - - format!( - r#" + match public_path.as_str() { + "runtime" => { + r#"/* mako/runtime/publicPath */ + !function () {{ + requireModule.publicPath= (typeof globalThis !== 'undefined' ? globalThis : self).publicPath || '/'; + }}();"#.to_string() + } + "auto" => { +r#"/* mako/runtime/publicPath */ +!function() {{ + var scriptUrl; + if (!self.document && self.importScripts) { + scriptUrl = self.location + ""; + } + if (!scriptUrl && document) { + if (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') + scriptUrl = document.currentScript.src; + if (!scriptUrl) { + var scripts = document.getElementsByTagName("script"); + if(scripts.length) { + var i = scripts.length - 1; + while (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src; + } + } + } + if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser"); + scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/"); + requireModule.publicPath = scriptUrl; +}}();"# + } + .to_string(), + _ => format!( + r#" /* mako/runtime/publicPath */ !function () {{ - requireModule.publicPath= {}; + requireModule.publicPath= "{}"; }}();"#, - public_path - ) + public_path + ), + } } fn helper_runtime(&self, context: &Arc) -> Result { diff --git a/docs/config.md b/docs/config.md index 2a5897b1a..5e9fb1f49 100644 --- a/docs/config.md +++ b/docs/config.md @@ -629,7 +629,11 @@ Buffer; - Type: `string` - Default: `"/"` -publicPath configuration. Note: There is a special value `"runtime"`, which means that it will switch to runtime mode and use the runtime `window.publicPath` as publicPath. +publicPath configuration. Note: There is two special values + +- `"runtime"`, which means that it will switch to runtime mode and use the runtime `window.publicPath` as publicPath. + +- `"auto"`, which is just like `publicPath: "auto"` in webpack If you want to set the `publicPath` in the runtime, use `__mako_public_path__`. (Notice: `__webpack_public_path__` is also supported) diff --git a/docs/config.zh-CN.md b/docs/config.zh-CN.md index 2558196f2..b23ced6ac 100644 --- a/docs/config.zh-CN.md +++ b/docs/config.zh-CN.md @@ -627,7 +627,9 @@ Buffer; - 类型:`string` - 默认值:`"/"` -publicPath 配置。注意:有一个特殊值 `"runtime"`,这意味着它将切换到运行时模式并使用运行时的 `window.publicPath` 作为 publicPath。 +publicPath 配置。注意:有两个特殊值 +* `"runtime"`,这意味着它将切换到运行时模式并使用运行时的 `window.publicPath` 作为 publicPath; +* `"auto"`,类似 webpack 的 `publicPath: "auto"`。 如果你想在运行时设置 `publicPath`,请使用 `__mako_public_path__`。(注:`__webpack_public_path__` 也是支持的) diff --git a/e2e/fixtures/config.public_path.auto/expect.js b/e2e/fixtures/config.public_path.auto/expect.js new file mode 100644 index 000000000..eb56350e5 --- /dev/null +++ b/e2e/fixtures/config.public_path.auto/expect.js @@ -0,0 +1,11 @@ +const assert = require("assert"); +const { parseBuildResult } = require("../../../scripts/test-utils"); +const { files } = parseBuildResult(__dirname); + +const content = files["index.js"]; + +assert.match( + content, + /scriptUrl = document.currentScript.src.*requireModule.publicPath = scriptUrl/s, + "requireModule.publicPath not correct" +); diff --git a/e2e/fixtures/config.public_path.auto/mako.config.json b/e2e/fixtures/config.public_path.auto/mako.config.json new file mode 100644 index 000000000..9d1978ca2 --- /dev/null +++ b/e2e/fixtures/config.public_path.auto/mako.config.json @@ -0,0 +1,3 @@ +{ + "publicPath": "auto" +} diff --git a/e2e/fixtures/config.public_path.auto/src/index.tsx b/e2e/fixtures/config.public_path.auto/src/index.tsx new file mode 100644 index 000000000..296d5492b --- /dev/null +++ b/e2e/fixtures/config.public_path.auto/src/index.tsx @@ -0,0 +1 @@ +console.log(1);