首页 > 解决方案 > 如果 Service Worker 要求 html 与 servive_worker.js 位于同一文件夹中,我该如何使用 EJS(需要 Views 文件夹)?

问题描述

我有一个非常简单的网络应用程序来练习制作 Service Worker。我遇到的问题是我正在使用 EJS,而 EJS 要求将 html 保存在 Views 文件夹中。要缓存 HTML,我必须将 service worker JS 文件放在与 HTML 相同的位置——但如果我这样做,它会失败!我收到一条错误消息,指出 HTML 必须位于 EJS 视图文件中

如果我将 HTML 移动到视图中,则不会出现错误,但 Service Worker 不会缓存任何内容!

请问有人可以给我建议吗?

这是我当前的文件夹结构,其中服务人员不会出错 - 但也不会缓存任何内容:

在此处输入图像描述

我会在哪里取出我的 EJS 文件以便缓存?它显然需要自己的文件夹来存放 HTML

这是我的 server.js:

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const request = require('request');
const apiKey = '<api key>';

app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));

app.set('view engine', 'ejs');


app.get('/', function (req, res) {
  res.render('weather_html');
})

app.post('/', function (req, res) {
  let city = req.body.city;
  let url = `http://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${apiKey}`
request(url, function (err, response, body) {
    if(err){
      res.render('weather_html', {weather: null, error: 'Error, please try again'});
    } else {
      let weather = JSON.parse(body)
      if(weather.main == undefined){
        res.render('weather_html', {weather: null, error: 'Error, please try again'});
      } else {
        let weatherText = `It's ${weather.main.temp} degrees in ${weather.name}!`;
        res.render('weather_html', {weather: weatherText, error: null});
      }
    }
  });
})

app.listen(3000, function () {
  console.log('server is listening on port 3000!')
});

这是混蛋 service_worker.js 文件:

const filesToCache = [
  '/'
];

const staticCacheName = 'this is the SW\'s cache';

self.addEventListener('install', event => {
  console.log('Attempting to install service worker and cache whatever is in filesToCache');
  event.waitUntil(
    caches.open(staticCacheName)
    .then(cache => {
      return cache.addAll(filesToCache);
    })
  );
});

self.addEventListener('fetch', event => {
  console.log('Fetch event for ', event.request.url);
  event.respondWith(
    caches.match(event.request)
    .then(response => {
      if (response) {
        console.log('Found ', event.request.url, ' in cache');
        return response;
      }
      console.log('Network request for ', event.request.url);
      return fetch(event.request)

      .then(response => {

  return caches.open(staticCacheName).then(cache => {
    cache.put(event.request.url, response.clone());
    return response;
  });
});

    }).catch(error => {

    })
  );
});

我的 EJS/HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test weather app</title>
    <link rel="stylesheet" type="text/css" href="/css/style.css">
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:300' rel='stylesheet' type='text/css'>
  </head>
  <body>
    <p>Test weather search app</p>
    <img src="https://ichef.bbci.co.uk/news/660/cpsprodpb/AECE/production/_99805744_gettyimages-625757214.jpg">
    <div class="container">
      <fieldset>
        <form action="/" method="post">
          <input name="city" type="text" class="ghost-input" placeholder="Enter a City" required>
          <input type="submit" class="ghost-button" value="Enter a city name for temperature in celsius">
        </form>
        <% if(locals.weather !== null){ %>
          <p><%= locals.weather %></p>
        <% } %>

        <% if(locals.error !== null){ %>
          <p><%= locals.error %></p>
        <% } %>
    </fieldset>
    </div>
  <!-- Service Worker - Checks if the browser supports a service worker, if so, registers the file server_worker.js as the SW, then logs to console-->
  <script>
  if('serviceWorker' in navigator) {
    navigator.serviceWorker
             .register('/service_worker.js')
             .then(function() { console.log("Service Worker Registered"); });
  }
</script>
  </body>
</html>

这是使用当前文件夹结构的 SW 没有错误的屏幕截图。我希望它能够在视图文件夹中缓存 HTML:

在此处输入图像描述

标签: javascriptnode.jsweb-servicesejshttp-caching

解决方案


您可以将文件夹的结构更改为:

在此处输入图像描述

然后在 server.js 文件中,您可以引用公用文件夹中的静态文件(并实际放置它们!):

app.use(express.static('public'));

另一个注意事项,我发现如果调用任何内容并返回 404 响应,则无法注册和安装 SWW


推荐阅读