为什么动态导入的 ESModule return JSON,当模块仅导出纯文本时?

Why does a dynamically imported ESModule return JSON, when the module exports only plaintext?

我相当熟悉 ES2015 Modules,但是,现在,我(同时)开始思考:

我确定我在这里遗漏了一些基本知识,但我找不到它。

我有两个版本的模板,如下所示:

template-static.ts

import page from './page.ts';

let template = page;  // Normally, the template will add a lot more to page

export default template;

template-dynamic.ts

const page = await import('./page.ts');

let template = page;  // Normally, the template will add a lot more to page

export default template;

在此测试设置中,每个模板(无论是使用静态导入还是动态导入)都导入相同的模块

page.ts

let page = `

  <h1>Test Page</h1>
  <p>This is the <strong>Test Page</strong>.</p>
  <ul>
    <li>Go to the <a href="/test-page-static-import/">Test Page (static import)</a> Page</li>
    <li>Go to the <a href="/test-page-dynamic-import/">Test Page (dynamic import)</a> Page</li>
  </ul>
`;

export default page;

最后,我有以下 HTTP 服务器(使用 Oak):

server.ts

import { Application, Router } from 'https://deno.land/x/oak/mod.ts';
import * as flags from 'https://deno.land/std/flags/mod.ts';

import templateStatic from './template-static.ts';
import templateDynamic from './template-dynamic.ts';

const {args} = Deno;
const DEFAULT_PORT = 8080;
const argPort = flags.parse(args).port;
const port = argPort ? Number(argPort) : DEFAULT_PORT;

const app = new Application();
const router = new Router();

app.use(router.routes());
app.use(router.allowedMethods());


router.get('/test-page-static-import', ({ response }: { response: any }) => {
    response.status = 200;
    response.headers.set('Content-Type', 'text/html');
    response.body = templateStatic;
});


router.get('/test-page-dynamic-import', ({ response }: { response: any }) => {
    response.status = 200;
    response.headers.set('Content-Type', 'text/html');
    response.body = templateDynamic;
});

console.log(`Server is running on port ${port}`)

await app.listen({ port });

当我将应用程序部署到 Heroku 时,它可以运行,但输出如下:

/测试页面静态导入

  <h1>Test Page</h1>
  <p>This is the <strong>Test Page</strong>.</p>
  <ul>
    <li>Go to the <a href="/test-page-static-import/">Test Page (static import)</a> Page</li>
    <li>Go to the <a href="/test-page-dynamic-import/">Test Page (dynamic import)</a> Page</li>
  </ul>

/测试页面动态导入

{"default":"\n\n  <h1>Test Page</h1>\n  <p>This is the <strong>Test Page</strong>.</p>\n  <ul>\n    <li>Go to the <a href=\"/test-page-static-import/\">Test Page (static import)</a> Page</li>\n    <li>Go to the <a href=\"/test-page-dynamic-import/\">Test Page (dynamic import)</a> Page</li>\n  </ul>\n"}

我很清楚,使用 static import 的模板正在导入 plaintext 并将其作为 text/html 使用,而使用 [=62] 的模板=]dynamic import 正在导入 JSON 并将其用作 text/html

为什么动态 import() 返回 JSON

原因是动态导入的 return 值不是您期望的默认导入,而是围绕它的对象包装器。

注意dynamic import webpack documentation上的例子。

return import('lodash')
    .then(({ default: _ }) => {
      const element = document.createElement('div');

      element.innerHTML = _.join(['Hello', 'webpack'], ' ');

如果您想从动态导入的文件访问默认导入,您必须通过 resolvedPromise.default 访问它。

在您的情况下,您可以从 page.ts 访问默认导入,如下所示:

const { default: page } = await import('./page.ts');

let template = page;

export default template;