Skip to content

WebApp

webapp 包可让你的 Meteor 应用向 Web 浏览器提供内容。它包含在 meteor-base 软件包集中,运行 meteor create 时会自动添加。你可以在没有它的情况下轻松构建 Meteor 应用 - 例如,如果你想制作一个仍然使用 Meteor 包系统和 DDP 的命令行工具。

¥The webapp package is what lets your Meteor app serve content to a web browser. It is included in the meteor-base set of packages that is automatically added when you run meteor create. You can easily build a Meteor app without it - for example if you wanted to make a command-line tool that still used the Meteor package system and DDP.

此软件包还允许你添加 HTTP 请求的处理程序。这允许其他服务通过 HTTP API 访问你应用的数据,从而使其能够轻松地与尚不支持 DDP 的工具和框架进行互操作。

¥This package also allows you to add handlers for HTTP requests. This lets other services access your app's data through an HTTP API, allowing it to easily interoperate with tools and frameworks that don't yet support DDP.

webapp 公开 express API 以通过 WebApp.handlers 处理请求。下面是可让你处理特定 URL 的示例:

¥webapp exposes the express API for handling requests through WebApp.handlers. Here's an example that will let you handle a specific URL:

js
// Listen to incoming HTTP requests (can only be used on the server).
WebApp.handlers.use("/hello", (req, res, next) => {
  res.writeHead(200);
  res.end(`Hello world from: ${Meteor.release}`);
});

WebApp.handlers

Server only

Summary:

Register a handler for all HTTP requests.

Arguments:

Source code
NameTypeDescriptionRequired
pathString

This handler will only be called on paths that match this string. The match has to border on a / or a ..

For example, /hello will match /hello/world and /hello.world, but not /hello_world.

No
handlerexpressHandlersCallback

A handler function that will be called on HTTP requests. See expressHandlersCallback

Yes
js
import { WebApp } from "meteor/webapp";


const result = WebApp.handlers();
  "path",  // this param is optional 
ExpressHandlersCallback,
);

expressHandlersCallback(req, res, next)

Server only

Summary:

callback handler for WebApp.expressHandlers

Arguments:

Source code
NameTypeDescriptionRequired
reqObject

a Node.js IncomingMessage object with some extra properties. This argument can be used to get information about the incoming request.

Yes
resObject

a Node.js ServerResponse object. Use this to write data that should be sent in response to the request, and call res.end() when you are done.

Yes
nextfunction

Calling this function will pass on the handling of this request to the next relevant handler.

Yes

提供静态登录页面

¥Serving a Static Landing Page

你可以使用 WebApp 做的一件非常酷的事情是为登录页面提供静态 HTML,其中 TTFB(第一个字节的时间)至关重要。

¥One of the really cool things you can do with WebApp is serve static HTML for a landing page where TTFB (time to first byte) is of utmost importance.

Bundle Visualizer动态导入 是帮助你最大程度缩短初始页面加载时间的绝佳工具。但有时你只需要将初始页面加载精简为裸机。

¥The Bundle Visualizer and Dynamic Imports are great tools to help you minimize initial page load times. But sometimes you just need to skinny down your initial page load to bare metal.

好消息是 WebApp 使这变得非常容易。

¥The good news is that WebApp makes this is really easy to do.

第一步是创建一个静态 HTML 文件并将其放置在应用根目录的私有文件夹中。

¥Step one is to create a your static HTML file and place it in the private folder at the root of your application.

下面是你可能用来开始的示例 index.html:

¥Here's a sample index.html you might use to get started:

html
<head>
    <title>Fast Landing Page</title>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no" />
    <link rel="stylesheet" href="path to your style sheet etc">
</head>

    <body>
        <!-- your content -->
    </body>

    <script>

    // any functions you need to support your landing page

    </script>

</html>
javascript
/* global WebApp Assets */
import crypto from "crypto";
import express from "express";

const router = express.Router();

router.get("/", async function (req, res, next) {
  const buf = await Assets.getTextAsync("index.html");

  if (buf.length > 0) {
    const eTag = crypto.createHash("md5").update(buf).digest("hex");

    if (req.headers["if-none-match"] === eTag) {
      res.writeHead(304, "Not Modified");
      return res.end();
    }

    res.writeHead(200, {
      ETag: eTag,
      "Content-Type": "text/html",
    });

    return res.end(buf);
  }

  return res.end("<html><body>Index page not found!</body></html>");
});

WebApp.handlers.use(router);

使用这种方法时需要考虑一些事项。

¥There are a couple things to think about with this approach.

我们正在使用 资源 模块读取 index.html 的内容,这使得从私有根文件夹中读取文件变得非常容易。

¥We're reading the contents of index.html using the Assets module that makes it really easy to read files out of the private root folder.

我们正在使用 connect-route NPM 包来简化 WebApp 路由处理。但你可以使用任何你想要了解请求内容的软件包。

¥We're using the connect-route NPM package to simplify WebApp route processing. But you can use any package you want to understand what is being requested.

最后,如果你决定使用这种技术,你需要确保你了解冲突的客户端路由将如何影响用户体验。

¥And finally, if you decide to use this technique you'll want to make sure you understand how conflicting client side routing will affect user experience.

动态运行时配置

¥Dynamic Runtime Configuration

在某些情况下,能够控制在运行时初始化 Meteor 的 meteo_runtime_config 变量很有价值。

¥In some cases it is valuable to be able to control the meteor_runtime_config variable that initializes Meteor at runtime.

示例

¥Example

有时单个 Meteor 服务器想要为多个 cordova 应用提供服务,每个应用都有一个唯一的 ROOT_URL。但有两个问题:

¥There are occasions when a single Meteor server would like to serve multiple cordova applications that each have a unique ROOT_URL. But there are 2 problems:

  1. Meteor 服务器只能配置为提供单个 ROOT_URL

    ¥The Meteor server can only be configured to serve a single ROOT_URL.

  2. cordova 应用在构建时配置了特定的 ROOT_URL

    ¥The cordova applications are build time configured with a specific ROOT_URL.

这 2 个条件会破坏 cordova 应用的 autoupdate。如果来自服务器的 ROOT_URL 与 cordova 应用的构建时配置的 ROOT_URL 不匹配,则 cordova-plugin-meteor-webapp 将更新失败。

¥These 2 conditions break autoupdate for the cordova applications. cordova-plugin-meteor-webapp will fail the update if the ROOT_URL from the server does not match the build time configured ROOT_URL of the cordova application.

为了解决这个问题,webapp 有一个用于在服务器上动态配置 __meteor_runtime_config__ 的钩子。

¥To remedy this problem webapp has a hook for dynamically configuring __meteor_runtime_config__ on the server.

动态运行时配置钩子

¥Dynamic Runtime Configuration Hook

js
WebApp.addRuntimeConfigHook(
  ({ arch, request, encodedCurrentConfig, updated }) => {
    // check the request to see if this is a request that requires
    // modifying the runtime configuration
    if (request.headers.domain === "calling.domain") {
      // make changes to the config for this domain
      // decode the current runtime config string into an object
      const config = WebApp.decodeRuntimeConfig(current);
      // make your changes
      config.newVar = "some value";
      config.oldVar = "new value";
      // encode the modified object to the runtime config string
      // and return it
      return WebApp.encodeRuntimeConfig(config);
    }
    // Not modifying other domains so return undefined
    return undefined;
  }
);

WebApp.addRuntimeConfigHook

Server only

Summary:

Hook that calls back when the meteor runtime configuration, __meteor_runtime_config__ is being sent to any client.

returns: Object { stop: function, callback: function }

  • stop Function Call stop() to stop getting callbacks.
  • callback Function The passed in callback.

Arguments:

Source code
NameTypeDescriptionRequired
callbackaddRuntimeConfigHookCallback

See addRuntimeConfigHookCallback description.

Yes
js
import { WebApp } from "meteor/webapp";

/** @returns Object */
const result = WebApp.addRuntimeConfigHook();
  addRuntimeConfigHookCallback
);

addRuntimeConfigHookCallback(options)

Server only

Summary:

Callback for addRuntimeConfigHook.

If the handler returns a falsy value the hook will not modify the runtime configuration.

If the handler returns a String the hook will substitute the string for the encoded configuration string.

Warning: the hook does not check the return value at all it is the responsibility of the caller to get the formatting correct using the helper functions.

addRuntimeConfigHookCallback takes only one Object argument with the following fields:

Arguments:

Source code
NameTypeDescriptionRequired
optionsObjectYes
options.archString

The architecture of the client requesting a new runtime configuration. This can be one of web.browser, web.browser.legacy or web.cordova.

Yes
options.requestObject

A NodeJs IncomingMessage https://nodejs.org/api/http.html#http_class_http_incomingmessage Object that can be used to get information about the incoming request.

Yes
options.encodedCurrentConfigString

The current configuration object encoded as a string for inclusion in the root html.

Yes
options.updatedBoolean

true if the config for this architecture has been updated since last called, otherwise false. This flag can be used to cache the decoding/encoding for each architecture.

Yes

此外,还有 2 个辅助函数可用于解码运行时配置字符串并编码运行时配置对象。

¥Additionally, 2 helper functions are available to decode the runtime config string and encode the runtime config object.

WebApp.decodeRuntimeConfig

Server only

Summary:

Takes an encoded runtime string and returns a runtime configuration object.

Arguments:

Source code
NameTypeDescriptionRequired
rtimeConfigStringString----Yes
js
import { WebApp } from "meteor/webapp";

/** @returns Object */
const result = WebApp.decodeRuntimeConfig();
  "rtimeConfigString"
);

WebApp.encodeRuntimeConfig

Server only

Summary:

Takes a runtime configuration object and returns an encoded runtime string.

Arguments:

Source code
NameTypeDescriptionRequired
rtimeConfigObject----Yes
js
import { WebApp } from "meteor/webapp";

/** @returns String */
const result = WebApp.encodeRuntimeConfig();
  rtimeConfig
);

更新运行时配置钩子

¥Updated Runtime Configuration Hook

js
const autoupdateCache;
// Get a notification when the runtime configuration is updated
// for each arch
WebApp.addUpdatedNotifyHook(({arch, manifest, runtimeConfig}) => {
  // Example, see if runtimeConfig.autoupdate has changed and if so
  // do something
  if(!_.isEqual(autoupdateCache, runtimeConfig.autoupdate)) {
    autoupdateCache = runtimeConfig.autoupdate;
    // do something...
  }
})

WebApp.addUpdatedNotifyHook

Server only

Summary:

Hook that runs when the meteor runtime configuration is updated. Typically the configuration only changes during development mode.

Arguments:

Source code
NameTypeDescriptionRequired
handleraddUpdatedNotifyHookCallback

The handler is called on every change to an arch runtime configuration. See addUpdatedNotifyHookCallback.

Yes
js
import { WebApp } from "meteor/webapp";

/** @returns Object */
const result = WebApp.addUpdatedNotifyHook();
  addUpdatedNotifyHookCallback
);

addUpdatedNotifyHookCallback(options)

Server only

Summary:

callback handler for addupdatedNotifyHook

Arguments:

Source code
NameTypeDescriptionRequired
optionsObjectYes
options.archString

The architecture that is being updated. This can be one of web.browser, web.browser.legacy or web.cordova.

Yes
options.manifestObject

The new updated manifest object for this arch.

Yes
options.runtimeConfigObject

The new updated configuration object for this arch.

Yes

main

Server only

Summary:

Starts the HTTP server. If UNIX_SOCKET_PATH is present Meteor's HTTP server will use that socket file for inter-process communication, instead of TCP. If you choose to not include webapp package in your application this method still must be defined for your Meteor application to work.