Codesandbox «Preview on edit» не работает для Aurelia, но работает с другими фреймворками и ванильным HTML - PullRequest
0 голосов
/ 07 января 2019

Я использую Codesandbox для создания образцов, а в новом проекте мы используем фреймворк Aurelia. Я могу заставить Аурелию работать на Codesandbox, но я не могу заставить 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>

1 Ответ

0 голосов
/ 09 января 2019

Рабочий пример с 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

...