Codesandbox “Preview on edit”不适用于 Aurelia,但适用于其他框架和原生 HTML

Posted

技术标签:

【中文标题】Codesandbox “Preview on edit”不适用于 Aurelia,但适用于其他框架和原生 HTML【英文标题】:Codesandbox "Preview on edit" does not work for Aurelia but works with other frameworks and vanilla HTML 【发布时间】:2019-06-02 07:25:21 【问题描述】:

我使用Codesandbox 创建示例,在一个新项目中我们使用框架Aurelia。我可以让 Aurelia 在 Codesandbox 上运行,但我无法让 Preview on edit 工作。我试图添加一个sandbox.config.json 并将Hard Reload on Change 设置为true,但它没有帮助。这不是一个交易破坏者,但是当您习惯于立即看到您的编辑时,它会很烦人。我认为问题在于使用的TemplateStatic,但是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>

【问题讨论】:

寻求调试帮助的问题必须包含在问题本身中重现它所需的最短代码。 minimal reproducible example 指向第三方网站的链接是不够的,因为链接会失效,并且会使您的问题和答案毫无意义。 @Rob True,但是这个问题特定于第三方站点,而不是实际代码本身。我现在已经添加了代码,但为了回答这个问题,它必须通过Codesandbox 运行。 我最近创建了一个aurelia demo on codesandbox,它运行良好。 (在我完成输入几秒钟后预览会更新)- 也许您可以分叉一个现有项目并将其替换为您的内容? @avrahamcool 那太好了:) 【参考方案1】:

使用 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 示例:

https://codesandbox.io/s/4ql5qvml49

【讨论】:

以上是关于Codesandbox “Preview on edit”不适用于 Aurelia,但适用于其他框架和原生 HTML的主要内容,如果未能解决你的问题,请参考以下文章

https://codesandbox.io 如何实现对本地版本的依赖

如何在“codesandbox.io”上配置 ESLint / Prettier 格式规则

CodeSandbox推出容器,进化为WebIDE

CodeSandbox:在节点模板中使用终端

运行浏览器内开发服务器 [如 stackblitz/codesandbox]

CodeSandbox.io <img> 标签未加载图像