[Web翻译]无构建开发(2):es-dev-server

1,527 阅读8分钟

原文地址:dev.to/open-wc/dev…

原文作者:dev.to/larsdenbakk…

发布时间:2019年8月4日 ・7分钟阅读

无构建开发(2):es-dev-server

本文是关于无构建开发系列的一部分。

  1. 简介
  2. es-dev-server(本文)
  3. 测试(即将推出)

介绍文章中,我们研究了不同的工作流和浏览器API。在这篇文章中,我们将探讨如何设置es-dev-server,以及它如何帮助我们在没有构建的情况下进行开发。

es-dev-server

es-dev-server是一个可组合的web服务器,它专注于开发者在开发时的生产力,而不需要构建步骤。通过选项,您可以选择额外的功能,如缓存、文件更改时的重载、SPA路由、解析裸模块导入和支持旧浏览器的兼容性模式。

设置

首先,让我们创建一个空的npm项目并安装es-dev-server

npm init
npm i -D es-dev-server。

在项目的根目录下创建一个index.html

<!DOCTYPE html>
<html>
<head></head>

<body>
  <div id="app"></div>
  <script type="module" src="./src/app.js"></script>
</body>

</html>

并创建一个虚拟的src/app.js文件。

console.log('hello world');

现在我们可以使用es-dev-server运行我们的应用程序了。

npx es-dev-server --open

没有任何额外的标志,es-dev-server就像一个普通的静态文件服务器。任何额外的功能都需要明确地启用。

裸体导入

在没有任何构建工具的情况下进行开发时,首先会遇到的问题之一就是如何处理裸模块的导入。

import foo from 'foo';

开箱即用,浏览器会抛出一个错误,因为它不知道如何处理这种导入。在我们之前的文章中,我们探讨了如何通过使用即将推出的浏览器API--import maps来使用这些导入。

在浏览器正确支持导入地图之前,我们可以使用开发服务器的--node-resolve标志。这将在向浏览器服务之前,使用NodeJS模块解析重写模块中的导入。

为了了解它是如何工作的,让我们将 lit-html,一个 HTML 模板库,添加到我们的项目中。

npm i -D lit-html

修改src/app.js来导入它。

import { render, html } from 'lit-html';

const template = html`<p>Hello world!</p>`;
render(template, document.getElementById('app'));

现在让我们重启服务器,添加节点解析标志。

npx es-dev-server --node-resolve --open

如果你检查网络选项卡,你会发现模块被正确地提供了预期的服务。src/app.js被重写成。

import { render, html } from './node_modules/lit-html/lit-html.js';

const template = html`<p>Hello world!</p>`;
render(template, document.getElementById('app'));

观看模式

一个很好的生产力提升器是在你编辑文件时重新加载浏览器。

要启用这个选项,使用watch标志重新启动服务器。

npx es-dev-server --watch --node-resolve --open

现在修改其中一个服务文件中的任何内容,例如app.js中的渲染html。你会看到浏览器自动用更新的代码重新加载。

重载是通过EventSource API完成的,Edge和IE11不支持该API。开发服务器注入一个小脚本,连接到一个消息通道端点。

缓存

es-dev-server 使用文件系统的最后修改时间戳,如果文件没有改变,则返回 304。这大大加快了重新加载的速度。您可以在浏览器中通过关闭Disable cache和刷新来测试这一点。

文件夹结构

不是每个项目的根目录下都有一个index.html。因为es-dev-server的工作方式和普通的web服务器一样,它可以从任何文件夹中提供文件。

例如,让我们创建一个名为demo的新文件夹,并将index.html移到里面。

我们需要调整脚本的src路径以反映这一变化。

<script type="module" src=".../src/app.js"></script>

而我们需要告诉服务器在demo文件夹内打开。

npx es-dev-server --node-resolve --open /demo/。

应用程序应在不做任何更改的情况下显示。

更改根目录

我们可能会想改变web服务器的根目录,以去除URL中的/demo/部分。

npx es-dev-server --root-dir /demo/ --open

但是,这样做是行不通的,因为Web服务器只能提供在其根目录下的文件。默认情况下,这是当前的工作目录。在我们的例子中,web服务器需要能够服务src文件夹的内容,以及node_modules文件夹。

这是在monorepo中工作时常见的问题,当你想从包子目录中服务文件时。许多你需要服务的模块都在项目的根目录下,所以你需要将根目录上移两级。

npx es-dev-server --root-dir .../.../ --open packages/my-package/index.html

SPA路由

如果你正在构建一个单页应用程序,你很可能正在做某种形式的前端路由。为了实现深度链接或刷新,Web服务器应该在更深的路径上返回你的index.html。这有时被称为历史API回退。

设置一个路由器超出了本文的范围,但是使用--app-index标志很容易启用这个选项。

npx es-dev-server --node-resolve --app-index index.html --open

当使用--app-index标志时,如果你没有向--open传递明确的路径,服务器将自动在你的应用程序的索引上打开服务器。

与旧版浏览器的兼容性

虽然我们可以使用最新版本的各大浏览器进行开发,但是在生产中还是需要支持老版本的浏览器。我们也可能会使用一些新的浏览器功能,而这些功能在所有主流浏览器的最新版本中还不支持。

如果我们每次要在这些浏览器上运行我们的应用时,都要运行一个生产版本,那就太可惜了。es-dev-server支持多种兼容性模式,可以帮助我们解决这个问题。

当兼容性模式被启用时,服务器会处理旧版浏览器所需的polyfills和代码转换。这使我们进入了构建工具的领域,所以我们不再是纯粹的 "没有构建工具的开发"。我认为这很好,因为我们只是为了浏览器的兼容性而使用它。你必须明确地选择加入这种行为。

让我们看看它是如何工作的。在app.js中添加一个动态导入,以便在点击按钮时懒惰加载一个模块。

import { html, render } from 'lit-html';

async function lazyLoad() {
  await import('lit-html/directives/until.js');
}

const template = html`
  <button @click=${lazyLoad}>Click me!</button>
`;
render(template, document.getElementById('app'));

动态导入并没有真正起到任何作用。如果我们在Chrome、Safari和Firefox上运行这段代码,就能正常工作。因为Edge还不支持动态导入,我们不能在那里运行这段代码。

我们可以开启最轻的兼容模式,esm,来处理这种情况。

npx es-dev-server --node-resolve --compatibility esm --open

启用esm后,es-dev-server会注入es-module-shims,并在你的索引中添加一个加载器脚本。你不需要为此改变任何代码。你可以在索引文件中查看注入的脚本。

有一些额外的模板,因为其他兼容模式可能会增加更多的polyfills。这些polyfills是经过哈希处理的,所以它们可以在浏览器中被积极地缓存。

除了esm,还有modernall兼容模式。这些模式为常见的浏览器API注入polyfills,并使用@babel/reset-env将最新的javascript语法转换为兼容格式。

modern兼容性模式下,您的代码将兼容最新的两个版本的Chrome、Safari、Firefox和Edge。

all兼容模式下,支持扩展到旧版浏览器,一直到IE11。在不支持es模块的浏览器上,它们将被转换为systemjs模块

这种转换会让服务器的速度变慢一些,所以我不建议在常规开发过程中使用modern或all模式。你可以在你的package.json中创建单独的脚本,只有当你在旧的浏览器上查看你的应用时,才以兼容模式运行。

esm模式对性能的影响可以忽略不计,所以应该可以使用。

导入地图

在上一篇文章中,我们简单地讨论了导入地图这个即将到来的浏览器功能,它可以处理裸模块的导入,es-module-shimssystemjs都支持导入地图。如果启用了兼容性模式,开发服务器就会负责调整你的导入地图,使其与这些库配合使用,这在开发过程中是一个可行的工作流程。

导入地图API还没有完全稳定下来,所以如果你要走这条路,最好关注一下这个标准的发展。请看这篇文章,了解使用导入地图的工作流程。

更多选择

查看官方文档,了解更多选项,例如将开发服务器作为库与其他工具集成,以及安装自定义中间件。

开始使用

要开始一个项目,为你设置开发服务器,使用open-wc项目框架。

npm init @open-wc

它用 lit-element 这个 web 组件库来设置项目,你可以把它换成你选择的任何库,设置不是针对 web 组件的。你可以把它换成任何你选择的库,这个设置并不针对web组件。


通过www.DeepL.com/Translator (免费版)翻译