[Front-End-Bereitstellung Teil 5] Verwenden von Docker zum Bereitstellen der nginx-Konfigurationsoptimierung für Single-Page-Anwendungen

Schaffen Sie weiter, beschleunigen Sie das Wachstum! Dies ist der erste Tag meiner Teilnahme an der „Nuggets Daily New Plan · June Update Challenge“, klicken Sie hier, um die Details der Veranstaltung anzuzeigen

Hallo zusammen, ich bin Shanyue, dies ist meine neu eröffnete Kolumne: Front-End Deployment Series . Einschließlich Docker, CICD usw. sieht das Übersichtsdiagramm wie folgt aus:

Gliederung

Darüber hinaus aktualisiert Bilibili verwandte Videos, siehe die Videoversion der Front-End- Bereitstellungsserie

Front-End-Bereitstellungsserie wird aktualisiert: 5/15


Im letzten Artikel haben wir die Caching-Optimierung mit Build-Caching und mehrstufigen Builds in Docker behandelt.

Aber bei der Bereitstellung von Single-Page-Anwendungen gibt es immer noch ein Problem, und das ist das clientseitige Routing.

In diesem Artikel wird ein einfacher One-Page-Router von Docker react-router-domimplementiert und bereitgestellt.

PS: Dieses Projekt verwendet das cra-deploy Warehouse als Übung, und die Konfigurationsdatei befindet sich in router.Dockerfile

Routing

Verwenden Sie diese Option, um eine Route react-domfür eine Single-Page-Anwendung hinzuzufügen. Da Routing nicht der Kerninhalt dieser Spalte ist, wird die Verwendung von Routing weggelassen. Der endgültige Code lautet wie folgt.

Der Quellcode befindet sich in cra-deploy/src/App.js

import logo from './logo.svg';
import './App.css';
import { Routes, Route, Link } from 'react-router-dom';

function Home() {
  return (
    <div>
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>当前在 Home 页面</h1>
        <Link to="/about" className="App-link">About</Link>
      </header>
    </div>
  )
}

function About() {
  return (
    <div>
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>当前在 About 页面</h1>
        <Link to="/" className="App-link">Home</Link>
      </header>
    </div>
  )
}

function App() {
  return (
    <div>
      <Routes>
        <Route index element={<Home />} />
        <Route path="about" element={<About />} />
      </Routes>
    </div>
  );
}

export default App;
复制代码

An dieser Stelle haben Sie zwei Routen:

  1. /,Titelseite
  2. /about, über Seite

Neu bereitstellen, es gibt ein Problem mit dem Routing

Stellen Sie die Seite gemäß der docker-composeKonfigurationsdatei erneut bereit.

$ docker-compose up --build simple
复制代码

An dieser Stelle https://localhost:4000/aboutwird ein 404 angezeigt.

404 Nicht gefunden

其实道理很简单:在静态资源中并没有 about 或者 about.html 该资源,因此返回 404 Not Found。而在单页应用中,/about 是由前端通过 history API 进行控制。

解决方法也很简单:在服务端将所有页面路由均指向 index.html,而单页应用再通过 history API 控制当前路由显示哪个页面。 这也是静态资源服务器的重写(Rewrite)功能。

我们在使用 nginx 镜像部署前端应用时,可通过挂载 nginx 配置解决该问题。

nginx 的 try_files 指令

在 nginx 中,可通过 try_files 指令将所有页面导向 index.html

location / {
    # 如果资源不存在,则回退到 index.html
    try_files  $uri $uri/ /index.html;  
}
复制代码

此时,可解决服务器端路由问题。

除此之外,我们还可以通过 nginx 配置解决更多问题。

长期缓存 (Long Term Cache)

在 CRA 应用中,./build/static 目录均由 webpack 构建产生,资源路径将会带有 hash 值。

$ tree ./build/static
./build/static
├── css
│   ├── main.073c9b0a.css
│   └── main.073c9b0a.css.map
├── js
│   ├── 787.cf6a8955.chunk.js
│   ├── 787.cf6a8955.chunk.js.map
│   ├── main.a3facdf8.js
│   ├── main.a3facdf8.js.LICENSE.txt
│   └── main.a3facdf8.js.map
└── media
    └── logo.6ce24c58023cc2f8fd88fe9d219db6c6.svg

3 directories, 8 files
复制代码

此时可通过 expires 对它们配置一年的长期缓存,它实际上是配置了 Cache-Control: max-age=31536000 的响应头。

那为什么带有 hash 的资源可设置长期缓存呢: **资源的内容发生变更,他将会生成全新的 hash 值,即全新的资源路径。**而旧有资源将不会进行访问。

location /static {
    expires 1y;
}
复制代码

nginx 配置文件

总结缓存策略如下:

  1. 带有 hash 的资源一年长期缓存
  2. 非带 hash 的资源,需要配置 Cache-Control: no-cache,避免浏览器默认为强缓存

Cache-Kontrolle

nginx.conf 文件需要维护在项目当中,经过路由问题的解决与缓存配置外,最终配置如下:

该 nginx 配置位于 cra-deploy/nginx.conf

server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.html index.htm;

    location / {
        # 解决单页应用服务端路由的问题
        try_files  $uri $uri/ /index.html;  

        # 非带 hash 的资源,需要配置 Cache-Control: no-cache,避免浏览器默认为强缓存
        expires -1;
    }

    location /static {
        # 带 hash 的资源,需要配置长期缓存
        expires 1y;
    }
}
复制代码

Dockerfile 配置文件

此时,在 Docker 部署过程中,需要将 nginx.conf 置于镜像中。

修改 router.Dockerfile 配置文件如下:

PS: 该 Dockerfile 配置位于 cra-deploy/router.Dockerfile

FROM node:14-alpine as builder

WORKDIR /code

# 单独分离 package.json,是为了 yarn 可最大限度利用缓存
ADD package.json yarn.lock /code/
RUN yarn

# 单独分离 public/src,是为了避免 ADD . /code 时,因为 Readme/nginx.conf 的更改避免缓存生效
# 也是为了 npm run build 可最大限度利用缓存
ADD public /code/public
ADD src /code/src
RUN npm run build

# 选择更小体积的基础镜像
FROM nginx:alpine
ADD nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder code/build /usr/share/nginx/html
复制代码

PS: 该 docker compose 配置位于 cra-deploy/router.Dockerfile

version: "3"
services:
  route:
    build:
      context: .
      dockerfile: router.Dockerfile
    ports:
      - 3000:80
复制代码

使用 docker-compose up --build route 启动容器。

  • 访问 http://localhost:3000 页面成功。
  • 访问 http://localhost:3000/about 页面成功。

检验长期缓存配置

访问 https://localhost:3000 页面,打开浏览器控制台网络面板。

此时对于带有 hash 资源, Cache-Control: max-age=31536000 响应头已配置。

此时对于非带 hash 资源, Cache-Control: no-cache 响应头已配置。

Einstellungen für Antwortheader anzeigen

百尺竿头更进一步

在前端部署流程中,一些小小的配置能大幅度提升性能,列举一二,感兴趣的同学可进一步探索。

构建资源的优化:

  1. 使用 terser 压缩 Javascript 资源
  2. 使用 cssnano 压缩 CSS 资源
  3. 使用 sharp/CDN 压缩 Image 资源或转化为 Webp
  4. 使用 webpack 将小图片转化为 DataURI
  5. 使用 webpack 进行更精细的分包,避免一行代码的改动使大量文件的缓存失效

小结

其实,从这里开始,前端部署与传统前端部署已逐渐显现了天壤之别。

Die traditionelle Frontend-Bereitstellung wird von Betrieb und Wartung dominiert.Jedes Mal, wenn es online geht, benachrichtigt es den Betrieb und die Wartung überdie Online -Schritte des Frontends des Projekts, das durch den Betrieb und die Wartungvervollständigt wird Front-End hat weniger Freiheit für die Bereitstellung.

Beispielsweise müssen das Öffnen der gzip/brotliKomprimierung , Cache-Controldie Steuerung von Antwortheadern und die Caching-Strategie verschiedener Routen benachrichtigt werden, dass der Betrieb und die Wartung abgeschlossen sind, und es ist schwierig, eine Versionsverwaltung zu haben .

Die Erweiterung der Frontend-Bereitstellungsfreiheit spiegelt sich in den folgenden zwei Aspekten wider:

  1. Containerisieren Sie das Front-End über Docker und müssen Sie die Betriebs- und Wartungsschritte nicht mehr online per E-Mail benachrichtigen
  2. Konfigurieren Sie nginx am Frontend über Docker und nginx-Konfigurationsdateien, einige kleine und triviale Konfigurationen, die stark mit dem Projekt zusammenhängen, erfordern keinen Eingriff in den Betrieb und die Wartung

An dieser Stelle ist das Kapitel zur Bereitstellung des Frontends in Docker beendet, und in der Praxis werden häufig statische Ressourcen im CDN platziert.

Wie geht man dann damit um?

Ich denke du magst

Origin juejin.im/post/7102057861320015885
Empfohlen
Rangfolge