Codesandbox "Preview on edit" 不适用于 Aurelia,但适用于其他框架和 vanilla HTML
Codesandbox "Preview on edit" does not work for Aurelia but works with other frameworks and vanilla HTML
我正在使用 Codesandbox
创建示例,在一个新项目中我们正在使用框架 Aurelia
。我可以在 Codesandbox
上获得 Aurelia 运行,但我无法让 Preview on edit
工作。我试图添加一个 sandbox.config.json
并将 Hard Reload on Change
设置为 true 但它没有帮助。这不是一个破坏交易的因素,但是当您习惯于立即看到您的编辑时,它会很烦人。我认为问题是使用的 Template
是 Static
,但是 Codesandbox
没有提供 Aurelia 模板。有人解决了吗?
Aurelia 代码示例,请参阅文件 app.html
:
https://codesandbox.io/s/n3yxrj9lwp
原版 HTML,请参阅文件 index.html
:
https://codesandbox.io/s/l73lnlvymq
反应,见文件 index.tsx
:
https://codesandbox.io/s/7w5yx8qmz1
代码:
index.html:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Aurelia App</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</head>
<body style='font-family:arial'>
<script src='https://unpkg.com/aurelia-script@1.3.0'></script>
</script>
<script>
const aurelia = new au.Aurelia();
aurelia
.use
.standardConfiguration()
.developmentLogging();
aurelia
.start()
.then(() => aurelia.setRoot('app.js', document.body))
.catch(ex => {
document.body.textContent = `Bootstrap error: ${ex.toString()}`;
});
</script>
</body>
</html>
app.js:
export class App {
constructor() {
this.message = "Aurelia Test";
}
}
app.html:
<template>
<div class="jumbotron mb-0"><h1>${message}</h1></div>
<div class="d-flex">Preview does not work here 1</div>
</template>
使用 Aurelia Framework 1.3.0 的工作示例:
app.html
<template>
<h1>${message}</h1>
</template>
app.js
export class App {
message = 'Hello World!';
}
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Aurelia App</title>
</head>
<body>
</body>
</html>
main.js
import { Aurelia } from "aurelia-framework";
export async function configure(aurelia) {
aurelia.use.standardConfiguration().developmentLogging();
await aurelia
.start()
.then(a => a.setRoot("app", document.body))
.catch(ex => {
document.body.textContent = `Bootstrap error: ${ex}`;
});
}
codesandbox.js
import "aurelia-polyfills";
import { initialize } from "aurelia-pal-browser";
import { Aurelia } from "aurelia-framework";
import { Origin } from "aurelia-metadata";
import { Loader, TemplateRegistryEntry, LoaderPlugin } from "aurelia-loader";
import { DOM, PLATFORM } from "aurelia-pal";
import { join } from "aurelia-path";
// IMPORTANT
// The code in this file is not needed in a real Aurelia app.
// It is only needed to configure CodeSandbox.io for Aurelia.
// Aurelia application code begins in the src/main.ts file.
// ORIGINAL AUTHOR: Bazyli Brzóska https://github.com/niieani
class TextTemplateLoader {
async loadTemplate(loader, entry) {
const text = await loader.loadText(entry.address);
entry.template = DOM.createTemplateFromMarkup(text);
}
}
function ensureOriginOnExports(moduleExports, moduleId) {
let target = moduleExports;
let key;
let exportedValue;
if (!moduleExports) {
return moduleExports;
}
if (target.__useDefault) {
target = target.default;
}
Origin.set(target, new Origin(moduleId, "default"));
if (typeof target === "object") {
for (key in target) {
exportedValue = target[key];
if (typeof exportedValue === "function") {
Origin.set(exportedValue, new Origin(moduleId, key));
}
}
}
return moduleExports;
}
async function getModule(moduleName) {
// if (moduleName.includes("/")) {
// moduleName = join("src", moduleName);
// }
const hasJS = moduleName.endsWith(".js");
try {
return await import(`${moduleName}` /* webpackMode: 'eager' */);
} catch (e) {}
try {
return await import(`./${moduleName}` /* webpackMode: 'eager' */);
} catch (e) {}
try {
return await import(`${moduleName}/dist/amd/${moduleName}` /* webpackMode: 'eager' */);
} catch (e) {}
try {
return await import(`./${moduleName}` /* webpackMode: 'eager' */);
} catch (e) {}
if (moduleName.includes("/")) {
try {
const [dep, ...path] = moduleName.split("/");
return import(`${dep}/dist/amd/${path.join(
"/"
)}` /* webpackMode: 'eager' */);
} catch (e) {}
}
if (!hasJS) {
return await getModule(`${moduleName}.js`);
}
}
class SandboxLoader extends Loader {
moduleRegistry = Object.create(null);
loaderPlugins = Object.create(null);
modulesBeingLoaded = new Map();
templateLoader: TextTemplateLoader;
constructor() {
super();
this.useTemplateLoader(new TextTemplateLoader());
this.addPlugin("template-registry-entry", {
fetch: async moduleId => {
const entry = this.getOrCreateTemplateRegistryEntry(moduleId);
if (!entry.templateIsLoaded) {
await this.templateLoader.loadTemplate(this, entry);
}
return entry;
}
});
}
async _import(address, defaultHMR = true) {
const addressParts = address.split("!");
const moduleId = addressParts.splice(addressParts.length - 1, 1)[0];
const loaderPlugin = addressParts.length === 1 ? addressParts[0] : null;
if (loaderPlugin) {
const plugin = this.loaderPlugins[loaderPlugin];
if (!plugin) {
throw new Error(
`Plugin ${loaderPlugin} is not registered in the loader.`
);
}
return await plugin.fetch(moduleId);
}
const m = await getModule(moduleId);
return m;
}
map(id, source) {}
normalizeSync(moduleId, relativeTo) {
return moduleId;
}
normalize(moduleId, relativeTo) {
return Promise.resolve(moduleId);
}
useTemplateLoader(templateLoader) {
this.templateLoader = templateLoader;
}
loadAllModules(ids) {
return Promise.all(ids.map(id => this.loadModule(id)));
}
async loadModule(moduleId, defaultHMR = true) {
let existing = this.moduleRegistry[moduleId];
if (existing) {
return existing;
}
let beingLoaded = this.modulesBeingLoaded.get(moduleId);
if (beingLoaded) {
return beingLoaded;
}
beingLoaded = this._import(moduleId, defaultHMR);
this.modulesBeingLoaded.set(moduleId, beingLoaded);
const moduleExports = await beingLoaded;
this.moduleRegistry[moduleId] = ensureOriginOnExports(
moduleExports,
moduleId
);
this.modulesBeingLoaded.delete(moduleId);
return moduleExports;
}
loadTemplate(url) {
return this.loadModule(
this.applyPluginToUrl(url, "template-registry-entry"),
false
);
}
async loadText(url) {
const result = await this.loadModule(url, false);
if (result.default && "string" == typeof result.default) {
// we're dealing with a file loaded using the css-loader:
return result.default;
}
return result;
}
applyPluginToUrl(url, pluginName) {
return `${pluginName}!${url}`;
}
addPlugin(pluginName, implementation) {
this.loaderPlugins[pluginName] = implementation;
}
}
(async () => {
try {
initialize();
const aurelia = new Aurelia(new SandboxLoader());
await getModule("./main").then(m => m.configure(aurelia));
} catch (ex) {
console.error(ex);
document.body.textContent = ex;
}
})();
package.json
{
"name": "a-simple-component",
"version": "1.0.0",
"private": true,
"keywords": [],
"description": "An Aurelia application that shows how to build a simple component.",
"main": "codesandbox.js",
"dependencies": {
"aurelia-event-aggregator": "1.0.1",
"aurelia-framework": "1.3.0",
"aurelia-history-browser": "1.2.0",
"aurelia-loader": "1.0.0",
"aurelia-logging": "1.5.0",
"aurelia-logging-console": "1.0.0",
"aurelia-metadata": "1.0.4",
"aurelia-pal": "1.8.0",
"aurelia-pal-browser": "1.8.0",
"aurelia-polyfills": "1.3.0",
"aurelia-router": "1.6.3",
"aurelia-templating": "1.10.1",
"aurelia-templating-binding": "1.5.2",
"aurelia-templating-resources": "1.7.1",
"aurelia-templating-router": "1.3.3"
}
}
https://codesandbox.io/s/849oxmjm82
Aurelia Framework 1.0.7 示例:
我正在使用 Codesandbox
创建示例,在一个新项目中我们正在使用框架 Aurelia
。我可以在 Codesandbox
上获得 Aurelia 运行,但我无法让 Preview on edit
工作。我试图添加一个 sandbox.config.json
并将 Hard Reload on Change
设置为 true 但它没有帮助。这不是一个破坏交易的因素,但是当您习惯于立即看到您的编辑时,它会很烦人。我认为问题是使用的 Template
是 Static
,但是 Codesandbox
没有提供 Aurelia 模板。有人解决了吗?
Aurelia 代码示例,请参阅文件 app.html
:
https://codesandbox.io/s/n3yxrj9lwp
原版 HTML,请参阅文件 index.html
:
https://codesandbox.io/s/l73lnlvymq
反应,见文件 index.tsx
:
https://codesandbox.io/s/7w5yx8qmz1
代码:
index.html:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Aurelia App</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</head>
<body style='font-family:arial'>
<script src='https://unpkg.com/aurelia-script@1.3.0'></script>
</script>
<script>
const aurelia = new au.Aurelia();
aurelia
.use
.standardConfiguration()
.developmentLogging();
aurelia
.start()
.then(() => aurelia.setRoot('app.js', document.body))
.catch(ex => {
document.body.textContent = `Bootstrap error: ${ex.toString()}`;
});
</script>
</body>
</html>
app.js:
export class App {
constructor() {
this.message = "Aurelia Test";
}
}
app.html:
<template>
<div class="jumbotron mb-0"><h1>${message}</h1></div>
<div class="d-flex">Preview does not work here 1</div>
</template>
使用 Aurelia Framework 1.3.0 的工作示例:
app.html
<template>
<h1>${message}</h1>
</template>
app.js
export class App {
message = 'Hello World!';
}
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Aurelia App</title>
</head>
<body>
</body>
</html>
main.js
import { Aurelia } from "aurelia-framework";
export async function configure(aurelia) {
aurelia.use.standardConfiguration().developmentLogging();
await aurelia
.start()
.then(a => a.setRoot("app", document.body))
.catch(ex => {
document.body.textContent = `Bootstrap error: ${ex}`;
});
}
codesandbox.js
import "aurelia-polyfills";
import { initialize } from "aurelia-pal-browser";
import { Aurelia } from "aurelia-framework";
import { Origin } from "aurelia-metadata";
import { Loader, TemplateRegistryEntry, LoaderPlugin } from "aurelia-loader";
import { DOM, PLATFORM } from "aurelia-pal";
import { join } from "aurelia-path";
// IMPORTANT
// The code in this file is not needed in a real Aurelia app.
// It is only needed to configure CodeSandbox.io for Aurelia.
// Aurelia application code begins in the src/main.ts file.
// ORIGINAL AUTHOR: Bazyli Brzóska https://github.com/niieani
class TextTemplateLoader {
async loadTemplate(loader, entry) {
const text = await loader.loadText(entry.address);
entry.template = DOM.createTemplateFromMarkup(text);
}
}
function ensureOriginOnExports(moduleExports, moduleId) {
let target = moduleExports;
let key;
let exportedValue;
if (!moduleExports) {
return moduleExports;
}
if (target.__useDefault) {
target = target.default;
}
Origin.set(target, new Origin(moduleId, "default"));
if (typeof target === "object") {
for (key in target) {
exportedValue = target[key];
if (typeof exportedValue === "function") {
Origin.set(exportedValue, new Origin(moduleId, key));
}
}
}
return moduleExports;
}
async function getModule(moduleName) {
// if (moduleName.includes("/")) {
// moduleName = join("src", moduleName);
// }
const hasJS = moduleName.endsWith(".js");
try {
return await import(`${moduleName}` /* webpackMode: 'eager' */);
} catch (e) {}
try {
return await import(`./${moduleName}` /* webpackMode: 'eager' */);
} catch (e) {}
try {
return await import(`${moduleName}/dist/amd/${moduleName}` /* webpackMode: 'eager' */);
} catch (e) {}
try {
return await import(`./${moduleName}` /* webpackMode: 'eager' */);
} catch (e) {}
if (moduleName.includes("/")) {
try {
const [dep, ...path] = moduleName.split("/");
return import(`${dep}/dist/amd/${path.join(
"/"
)}` /* webpackMode: 'eager' */);
} catch (e) {}
}
if (!hasJS) {
return await getModule(`${moduleName}.js`);
}
}
class SandboxLoader extends Loader {
moduleRegistry = Object.create(null);
loaderPlugins = Object.create(null);
modulesBeingLoaded = new Map();
templateLoader: TextTemplateLoader;
constructor() {
super();
this.useTemplateLoader(new TextTemplateLoader());
this.addPlugin("template-registry-entry", {
fetch: async moduleId => {
const entry = this.getOrCreateTemplateRegistryEntry(moduleId);
if (!entry.templateIsLoaded) {
await this.templateLoader.loadTemplate(this, entry);
}
return entry;
}
});
}
async _import(address, defaultHMR = true) {
const addressParts = address.split("!");
const moduleId = addressParts.splice(addressParts.length - 1, 1)[0];
const loaderPlugin = addressParts.length === 1 ? addressParts[0] : null;
if (loaderPlugin) {
const plugin = this.loaderPlugins[loaderPlugin];
if (!plugin) {
throw new Error(
`Plugin ${loaderPlugin} is not registered in the loader.`
);
}
return await plugin.fetch(moduleId);
}
const m = await getModule(moduleId);
return m;
}
map(id, source) {}
normalizeSync(moduleId, relativeTo) {
return moduleId;
}
normalize(moduleId, relativeTo) {
return Promise.resolve(moduleId);
}
useTemplateLoader(templateLoader) {
this.templateLoader = templateLoader;
}
loadAllModules(ids) {
return Promise.all(ids.map(id => this.loadModule(id)));
}
async loadModule(moduleId, defaultHMR = true) {
let existing = this.moduleRegistry[moduleId];
if (existing) {
return existing;
}
let beingLoaded = this.modulesBeingLoaded.get(moduleId);
if (beingLoaded) {
return beingLoaded;
}
beingLoaded = this._import(moduleId, defaultHMR);
this.modulesBeingLoaded.set(moduleId, beingLoaded);
const moduleExports = await beingLoaded;
this.moduleRegistry[moduleId] = ensureOriginOnExports(
moduleExports,
moduleId
);
this.modulesBeingLoaded.delete(moduleId);
return moduleExports;
}
loadTemplate(url) {
return this.loadModule(
this.applyPluginToUrl(url, "template-registry-entry"),
false
);
}
async loadText(url) {
const result = await this.loadModule(url, false);
if (result.default && "string" == typeof result.default) {
// we're dealing with a file loaded using the css-loader:
return result.default;
}
return result;
}
applyPluginToUrl(url, pluginName) {
return `${pluginName}!${url}`;
}
addPlugin(pluginName, implementation) {
this.loaderPlugins[pluginName] = implementation;
}
}
(async () => {
try {
initialize();
const aurelia = new Aurelia(new SandboxLoader());
await getModule("./main").then(m => m.configure(aurelia));
} catch (ex) {
console.error(ex);
document.body.textContent = ex;
}
})();
package.json
{
"name": "a-simple-component",
"version": "1.0.0",
"private": true,
"keywords": [],
"description": "An Aurelia application that shows how to build a simple component.",
"main": "codesandbox.js",
"dependencies": {
"aurelia-event-aggregator": "1.0.1",
"aurelia-framework": "1.3.0",
"aurelia-history-browser": "1.2.0",
"aurelia-loader": "1.0.0",
"aurelia-logging": "1.5.0",
"aurelia-logging-console": "1.0.0",
"aurelia-metadata": "1.0.4",
"aurelia-pal": "1.8.0",
"aurelia-pal-browser": "1.8.0",
"aurelia-polyfills": "1.3.0",
"aurelia-router": "1.6.3",
"aurelia-templating": "1.10.1",
"aurelia-templating-binding": "1.5.2",
"aurelia-templating-resources": "1.7.1",
"aurelia-templating-router": "1.3.3"
}
}
https://codesandbox.io/s/849oxmjm82
Aurelia Framework 1.0.7 示例: