mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-05 03:50:29 +01:00
fix(docker): send ROBOTS_NOINDEX as a header, make COMPRESSION_MODE work and fix the Docker guide example
This commit is contained in:
+1
-1
@@ -21,7 +21,7 @@ ARG SIMPLE_MODE=false
|
||||
ENV SIMPLE_MODE=$SIMPLE_MODE
|
||||
ARG DISABLE_GITHUB_STARS=false
|
||||
ENV DISABLE_GITHUB_STARS=$DISABLE_GITHUB_STARS
|
||||
ARG COMPRESSION_MODE=all
|
||||
ARG COMPRESSION_MODE=o
|
||||
ENV COMPRESSION_MODE=$COMPRESSION_MODE
|
||||
|
||||
# global arg to local arg - BASE_URL is read from env by vite.config.ts
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ ARG SIMPLE_MODE=false
|
||||
ENV SIMPLE_MODE=$SIMPLE_MODE
|
||||
ARG DISABLE_GITHUB_STARS=false
|
||||
ENV DISABLE_GITHUB_STARS=$DISABLE_GITHUB_STARS
|
||||
ARG COMPRESSION_MODE=all
|
||||
ARG COMPRESSION_MODE=o
|
||||
ENV COMPRESSION_MODE=$COMPRESSION_MODE
|
||||
|
||||
ARG BASE_URL
|
||||
|
||||
@@ -432,32 +432,34 @@ npm run preview
|
||||
|
||||
**Compression Modes:**
|
||||
|
||||
BentoPDF supports different compression modes for optimized builds:
|
||||
By default the build saves no compressed copies, and your server or host compresses files as it sends them. If your server can send precompressed files (nginx `gzip_static` or `brotli_static`, Apache, Caddy `precompressed`), set `COMPRESSION_MODE` to save `.gz` and/or `.br` copies next to each text and WASM file. The originals are always kept.
|
||||
|
||||
The prebuilt Docker images have no copies, and their nginx compresses with gzip on the fly. Build your own image with `COMPRESSION_MODE=g` to have it serve `.gz` copies instead. The image's nginx can't serve brotli, so for brotli put a proxy or CDN that compresses with brotli, such as Traefik or Cloudflare, in front of it.
|
||||
|
||||
```bash
|
||||
# Gzip only (smallest Docker image size)
|
||||
npm run build:gzip
|
||||
docker build --build-arg COMPRESSION_MODE=g -t bentopdf:gzip .
|
||||
|
||||
# Brotli only (best compression ratio)
|
||||
npm run build:brotli
|
||||
docker build --build-arg COMPRESSION_MODE=b -t bentopdf:brotli .
|
||||
|
||||
# No compression (fastest build time)
|
||||
# No copies (default)
|
||||
npm run build:original
|
||||
docker build --build-arg COMPRESSION_MODE=o -t bentopdf:original .
|
||||
|
||||
# All formats (default, maximum browser compatibility)
|
||||
# Gzip copies
|
||||
npm run build:gzip
|
||||
docker build --build-arg COMPRESSION_MODE=g -t bentopdf:gzip .
|
||||
|
||||
# Brotli copies
|
||||
npm run build:brotli
|
||||
docker build --build-arg COMPRESSION_MODE=b -t bentopdf:brotli .
|
||||
|
||||
# Both
|
||||
npm run build:all
|
||||
docker build --build-arg COMPRESSION_MODE=all -t bentopdf:all .
|
||||
```
|
||||
|
||||
| Mode | Files Kept | Use Case |
|
||||
| ----- | ----------- | --------------------------------- |
|
||||
| `g` | `.gz` only | Standard nginx or minimal size |
|
||||
| `b` | `.br` only | Modern CDN with Brotli support |
|
||||
| `o` | originals | Development or custom compression |
|
||||
| `all` | all formats | Maximum compatibility (default) |
|
||||
| Mode | Copies made | Use case |
|
||||
| ----- | --------------- | ------------------------------------- |
|
||||
| `o` | none | Default, server compresses on the fly |
|
||||
| `g` | `.gz` | nginx with `gzip_static` |
|
||||
| `b` | `.br` | Servers with `brotli_static` |
|
||||
| `all` | `.gz` and `.br` | Servers that serve both |
|
||||
|
||||
**CDN Optimization:**
|
||||
|
||||
|
||||
+6
-4
@@ -111,10 +111,12 @@ build with a custom `SITE_URL` marks every page `noindex`.
|
||||
### Stay invisible to search engines (no SEO competition either way)
|
||||
|
||||
Set the runtime environment variable `ROBOTS_NOINDEX=true`. The container
|
||||
injects `<meta name="robots" content="noindex, follow">` into every served
|
||||
HTML file at startup. The canonical link still points at the official site
|
||||
by default, so when crawlers do follow internal links they still see
|
||||
bentopdf.com as the authoritative source.
|
||||
then sends an `X-Robots-Tag: noindex, follow` header with every response.
|
||||
The canonical link still points at the official site by default, so when
|
||||
crawlers do follow internal links they still see bentopdf.com as the
|
||||
authoritative source. `ROBOTS_NOINDEX` only works in the Docker image; if
|
||||
you serve the files yourself, build with your own `SITE_URL` instead (see
|
||||
above).
|
||||
|
||||
```sh
|
||||
docker run -d -p 8080:8080 -e ROBOTS_NOINDEX=true ghcr.io/alam00000/bentopdf:latest
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | تخطي جلب عدد نجوم GitHub عند تحميل الصفحة وحذف `api.github.com` من CSP. عمليات بناء Simple Mode تتخطاه دائمًا. | `false` |
|
||||
| `SITE_URL` | العنوان العام المكتوب في روابط canonical وhreflang وخريطة الموقع. اتركه على الافتراضي ما لم تكن تريد أن تعامل محركات البحث نشرك كموقع مستقل. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | مع `SITE_URL` مخصص، توضع على كل صفحة علامة `noindex` لكي لا تنافس نسختك bentopdf.com في نتائج البحث. اضبطه على `true` للسماح لمحركات البحث بفهرستها. | `false` |
|
||||
| `COMPRESSION_MODE` | نسخ مضغوطة مسبقًا: `o` بلا نسخ، `g` `.gz` (يقدّمها nginx داخل الصورة)، `b` `.br`، `all` كلاهما. لا يستطيع nginx داخل الصورة تقديم `.br`. | `o` |
|
||||
|
||||
عناوين وحدات WASM مُعدّة مسبقًا بقيم CDN افتراضية، فتعمل جميع الميزات المتقدمة مباشرة. غيّرها في عمليات النشر المعزولة عن الإنترنت أو المستضافة ذاتيًا.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Не загружаць колькасць зорак GitHub пры загрузцы старонкі і прыбраць `api.github.com` з CSP. Зборкі Simple Mode заўсёды гэта прапускаюць. | `false` |
|
||||
| `SITE_URL` | Публічны URL для спасылак canonical, hreflang і sitemap. Пакіньце значэнне па змаўчанні, калі не хочаце, каб пошукавыя сістэмы лічылі ваша разгортванне асобным сайтам. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | З уласным `SITE_URL` кожная старонка пазначаецца `noindex`, каб ваша копія не канкурыравала з bentopdf.com у выніках пошуку. Задайце `true`, каб дазволіць індэксацыю. | `false` |
|
||||
| `COMPRESSION_MODE` | Папярэдне сціснутыя копіі побач з кожным файлам: `o` няма, `g` `.gz` (іх аддае nginx вобраза), `b` `.br`, `all` абедзве. Nginx вобраза не ўмее аддаваць `.br`. | `o` |
|
||||
|
||||
URL модуляў WASM загадзя настроены на CDN па змаўчанні: усе пашыраныя функцыі працуюць адразу. Перавызначце іх для ізаляваных або ўласных разгортванняў.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Omet la consulta del nombre d'estrelles de GitHub en carregar la pàgina i elimina `api.github.com` de la CSP. Les compilacions en mode simple sempre l'ometen. | `false` |
|
||||
| `SITE_URL` | URL pública escrita als enllaços canonical, hreflang i del mapa del lloc. Deixa-la per defecte tret que vulguis que els cercadors tractin el teu desplegament com un lloc propi. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Amb un `SITE_URL` personalitzat, totes les pàgines es marquen com a `noindex` perquè la teva còpia no competeixi amb bentopdf.com als resultats de cerca. Defineix-ho a `true` perquè els cercadors l'indexin. | `false` |
|
||||
| `COMPRESSION_MODE` | Còpies precomprimides que es desen al costat de cada fitxer: `o` cap, `g` `.gz` (les serveix el nginx de la imatge), `b` `.br`, `all` totes dues. El nginx de la imatge no pot servir `.br`. | `o` |
|
||||
|
||||
Les URL dels mòduls WASM vénen preconfigurades amb CDN per defecte, així que totes les funcions avançades funcionen directament. Substitueix-les en desplegaments aïllats de la xarxa o autoallotjats.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Spring hentningen af GitHub-stjerneantal over ved sideindlæsning, og fjern `api.github.com` fra CSP. Simple Mode-builds springer den altid over. | `false` |
|
||||
| `SITE_URL` | Offentlig URL, der skrives i canonical-, hreflang- og sitemap-links. Lad den stå på standardværdien, medmindre du vil have søgemaskiner til at behandle din installation som et eget site. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Med en brugerdefineret `SITE_URL` markeres hver side `noindex`, så din kopi ikke konkurrerer med bentopdf.com i søgeresultaterne. Sæt til `true` for at lade søgemaskiner indeksere den. | `false` |
|
||||
| `COMPRESSION_MODE` | Forhåndskomprimerede kopier, der gemmes ved siden af hver fil: `o` ingen, `g` `.gz` (serveres af imagets nginx), `b` `.br`, `all` begge. Imagets nginx kan ikke servere `.br`. | `o` |
|
||||
|
||||
WASM-modul-URL'erne er forudkonfigureret med CDN-standarder, så alle avancerede funktioner virker fra start. Overskriv dem til air-gapped eller selvhostede installationer.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Überspringt den Abruf der GitHub-Sterne beim Laden der Seite und entfernt `api.github.com` aus der CSP. Simple-Mode-Builds überspringen ihn immer. | `false` |
|
||||
| `SITE_URL` | Öffentliche URL, die in Canonical-, hreflang- und Sitemap-Links geschrieben wird. Lassen Sie den Standard, sofern Suchmaschinen Ihre Bereitstellung nicht als eigene Website behandeln sollen. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Bei einer eigenen `SITE_URL` wird jede Seite mit `noindex` markiert, damit Ihre Kopie in den Suchergebnissen nicht mit bentopdf.com konkurriert. Mit `true` dürfen Suchmaschinen sie indexieren. | `false` |
|
||||
| `COMPRESSION_MODE` | Vorkomprimierte Kopien: `o` keine, `g` `.gz` (vom nginx des Images ausgeliefert), `b` `.br`, `all` beide. Der nginx des Images kann `.br` nicht ausliefern. | `o` |
|
||||
|
||||
Die WASM-Modul-URLs sind mit CDN-Standardwerten vorkonfiguriert, sodass alle erweiterten Funktionen sofort funktionieren. Überschreiben Sie sie für abgeschottete oder selbst gehostete Bereitstellungen.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Omite la obtención del contador de estrellas de GitHub al cargar la página y elimina `api.github.com` de la CSP. Las compilaciones en Simple Mode siempre la omiten. | `false` |
|
||||
| `SITE_URL` | URL pública escrita en los enlaces canonical, hreflang y de sitemap. Déjala por defecto salvo que quieras que los buscadores traten tu despliegue como un sitio propio. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Con un `SITE_URL` personalizado, todas las páginas se marcan como `noindex` para que tu copia no compita con bentopdf.com en los resultados de búsqueda. Ponlo en `true` para que los buscadores la indexen. | `false` |
|
||||
| `COMPRESSION_MODE` | Copias precomprimidas que se guardan junto a cada archivo: `o` ninguna, `g` `.gz` (las sirve el nginx de la imagen), `b` `.br`, `all` ambas. El nginx de la imagen no puede servir `.br`. | `o` |
|
||||
|
||||
Las URL de los módulos WASM vienen preconfiguradas con valores predeterminados de CDN, así que todas las funciones avanzadas funcionan desde el primer momento. Sobrescríbelas para despliegues aislados de la red o autoalojados.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | از دریافت تعداد ستارههای GitHub هنگام بارگذاری صفحه صرفنظر میکند و `api.github.com` را از CSP حذف میکند. ساختهای Simple Mode همیشه از آن صرفنظر میکنند. | `false` |
|
||||
| `SITE_URL` | URL عمومی که در پیوندهای canonical، hreflang و sitemap نوشته میشود. آن را روی پیشفرض نگه دارید، مگر اینکه بخواهید موتورهای جستجو استقرار شما را سایتی مستقل بدانند. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | با `SITE_URL` سفارشی، همهٔ صفحات `noindex` علامتگذاری میشوند تا نسخهٔ شما در نتایج جستجو با bentopdf.com رقابت نکند. برای اجازهٔ نمایهسازی به موتورهای جستجو، آن را `true` کنید. | `false` |
|
||||
| `COMPRESSION_MODE` | نسخههای ازپیشفشردهای که کنار هر فایل ذخیره میشوند: `o` هیچ، `g` `.gz` (توسط nginx ایمیج ارائه میشود)، `b` `.br`، `all` هر دو. nginx ایمیج نمیتواند `.br` را ارائه کند. | `o` |
|
||||
|
||||
URLهای ماژولهای WASM با پیشفرضهای CDN از پیش پیکربندی شدهاند؛ همهٔ قابلیتهای پیشرفته بلافاصله کار میکنند. برای استقرارهای ایزوله یا میزبانی شخصی، اینها را بازنویسی کنید.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Ignore la récupération du nombre d'étoiles GitHub au chargement de la page et retire `api.github.com` de la CSP. Les builds en Simple Mode l'ignorent toujours. | `false` |
|
||||
| `SITE_URL` | URL publique écrite dans les liens canonical, hreflang et sitemap. Laissez la valeur par défaut, sauf si vous voulez que les moteurs de recherche traitent votre déploiement comme un site à part entière. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Avec un `SITE_URL` personnalisé, chaque page est marquée `noindex` pour que votre copie ne concurrence pas bentopdf.com dans les résultats de recherche. Définissez `true` pour autoriser l'indexation par les moteurs de recherche. | `false` |
|
||||
| `COMPRESSION_MODE` | Copies précompressées enregistrées à côté de chaque fichier : `o` aucune, `g` `.gz` (servies par le nginx de l'image), `b` `.br`, `all` les deux. Le nginx de l'image ne peut pas servir `.br`. | `o` |
|
||||
|
||||
Les URL des modules WASM sont préconfigurées avec des valeurs CDN par défaut : toutes les fonctionnalités avancées fonctionnent sans configuration. Remplacez-les pour les déploiements isolés du réseau ou auto-hébergés.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Lewati pengambilan jumlah bintang GitHub saat halaman dimuat dan hapus `api.github.com` dari CSP. Build Simple Mode selalu melewatinya. | `false` |
|
||||
| `SITE_URL` | URL publik yang ditulis ke tautan canonical, hreflang, dan sitemap. Biarkan default kecuali Anda ingin mesin pencari memperlakukan deployment Anda sebagai situs tersendiri. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Dengan `SITE_URL` kustom, setiap halaman ditandai `noindex` agar salinan Anda tidak bersaing dengan bentopdf.com di hasil pencarian. Atur ke `true` agar mesin pencari mengindeksnya. | `false` |
|
||||
| `COMPRESSION_MODE` | Salinan terkompresi: `o` tidak ada, `g` `.gz` (disajikan oleh nginx di image), `b` `.br`, `all` keduanya. Nginx di image tidak bisa menyajikan `.br`. | `o` |
|
||||
|
||||
URL modul WASM sudah dikonfigurasi dengan default CDN, sehingga semua fitur lanjutan langsung berfungsi. Timpa nilai ini untuk deployment air-gapped atau hosting mandiri.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Salta il recupero del numero di stelle GitHub al caricamento della pagina e rimuove `api.github.com` dalla CSP. Le build in Simple Mode lo saltano sempre. | `false` |
|
||||
| `SITE_URL` | URL pubblico scritto nei link canonical, hreflang e sitemap. Lascia il valore predefinito, a meno che tu non voglia che i motori di ricerca trattino la tua installazione come un sito a sé. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Con un `SITE_URL` personalizzato, ogni pagina è marcata `noindex` così la tua copia non compete con bentopdf.com nei risultati di ricerca. Imposta `true` per permettere ai motori di ricerca di indicizzarla. | `false` |
|
||||
| `COMPRESSION_MODE` | Copie precompresse da salvare accanto a ogni file: `o` nessuna, `g` `.gz` (servite dal nginx dell'immagine), `b` `.br`, `all` entrambe. Il nginx dell'immagine non può servire `.br`. | `o` |
|
||||
|
||||
Gli URL dei moduli WASM sono preconfigurati con i valori CDN predefiniti: tutte le funzionalità avanzate funzionano subito. Sostituiscili per installazioni air-gapped o self-hosted.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | ページ読み込み時のGitHubスター数の取得をスキップし、CSPから `api.github.com` を除外します。Simple Modeのビルドでは常にスキップされます。 | `false` |
|
||||
| `SITE_URL` | canonical、hreflang、サイトマップのリンクに書き込まれる公開URL。検索エンジンにデプロイ先を独立したサイトとして扱わせたい場合を除き、デフォルトのままにしてください。 | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | カスタムの `SITE_URL` を使う場合、検索結果でbentopdf.comと競合しないよう、すべてのページが `noindex` になります。検索エンジンにインデックスさせるには `true` に設定します。 | `false` |
|
||||
| `COMPRESSION_MODE` | 各ファイルの横に保存する事前圧縮コピー:`o` なし、`g` `.gz`(イメージのnginxが配信)、`b` `.br`、`all` 両方。イメージのnginxは `.br` を配信できません。 | `o` |
|
||||
|
||||
WASMモジュールのURLには、CDNのデフォルトがあらかじめ設定されているため、高度な機能はすべてそのまま動作します。エアギャップ環境やセルフホスト環境では、これらを上書きしてください。
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | 페이지 로드 시 GitHub 스타 수 가져오기를 건너뛰고 CSP에서 `api.github.com`을 제거합니다. Simple Mode 빌드는 항상 건너뜁니다. | `false` |
|
||||
| `SITE_URL` | canonical, hreflang, 사이트맵 링크에 기록되는 공개 URL입니다. 검색 엔진이 사용자의 배포를 독립된 사이트로 취급하길 원하지 않는다면 기본값으로 두세요. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | 사용자 지정 `SITE_URL`을 사용하면 모든 페이지가 `noindex`로 표시되어 사용자의 사본이 검색 결과에서 bentopdf.com과 경쟁하지 않습니다. 검색 엔진이 색인하도록 하려면 `true`로 설정하세요. | `false` |
|
||||
| `COMPRESSION_MODE` | 각 파일 옆에 저장할 사전 압축 사본: `o` 없음, `g` `.gz` (이미지의 nginx가 제공), `b` `.br`, `all` 둘 다. 이미지의 nginx는 `.br`을 제공할 수 없습니다. | `o` |
|
||||
|
||||
WASM 모듈 URL에는 CDN 기본값이 미리 설정되어 있어 모든 고급 기능이 별도 설정 없이 작동합니다. 폐쇄망이나 직접 호스팅하는 배포에서는 이 값을 덮어쓰세요.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Sla het ophalen van het aantal GitHub-sterren bij het laden van de pagina over en haal `api.github.com` uit de CSP. Builds in Simple Mode slaan het altijd over. | `false` |
|
||||
| `SITE_URL` | Openbare URL die in canonical-, hreflang- en sitemaplinks wordt geschreven. Laat de standaardwaarde staan, tenzij zoekmachines je implementatie als eigen site moeten zien. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Bij een aangepaste `SITE_URL` krijgt elke pagina `noindex`, zodat je kopie niet concurreert met bentopdf.com in zoekresultaten. Zet op `true` om indexering toe te staan. | `false` |
|
||||
| `COMPRESSION_MODE` | Voorgecomprimeerde kopieën: `o` geen, `g` `.gz` (geserveerd door de nginx van de image), `b` `.br`, `all` beide. De nginx van de image kan `.br` niet serveren. | `o` |
|
||||
|
||||
WASM-module-URL's zijn vooraf geconfigureerd met CDN-standaardwaarden, dus alle geavanceerde functies werken direct. Overschrijf ze voor air-gapped of zelfgehoste implementaties.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Pomija pobieranie liczby gwiazdek GitHub przy ładowaniu strony i usuwa `api.github.com` z CSP. Buildy Simple Mode zawsze to pomijają. | `false` |
|
||||
| `SITE_URL` | Publiczny adres URL zapisywany w linkach canonical, hreflang i mapy witryny. Zostaw domyślny, chyba że chcesz, aby wyszukiwarki traktowały Twoje wdrożenie jako osobną witrynę. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Przy własnym `SITE_URL` każda strona jest oznaczana jako `noindex`, aby Twoja kopia nie konkurowała z bentopdf.com w wynikach wyszukiwania. Ustaw `true`, aby pozwolić wyszukiwarkom ją indeksować. | `false` |
|
||||
| `COMPRESSION_MODE` | Wstępnie skompresowane kopie zapisywane obok każdego pliku: `o` brak, `g` `.gz` (serwowane przez nginx w obrazie), `b` `.br`, `all` obie. Nginx w obrazie nie obsługuje `.br`. | `o` |
|
||||
|
||||
Adresy URL modułów WASM są wstępnie skonfigurowane z domyślnymi CDN, więc wszystkie zaawansowane funkcje działają od razu. Zmień je w środowiskach odciętych od sieci lub przy samodzielnym hostingu.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Pula a busca da contagem de estrelas do GitHub ao carregar a página e remove `api.github.com` da CSP. As versões Simple Mode sempre a dispensam. | `false` |
|
||||
| `SITE_URL` | URL pública gravada nos links canonical, hreflang e sitemap. Mantenha o padrão, a menos que queira que os mecanismos de busca tratem sua implantação como um site próprio. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Com um `SITE_URL` personalizado, todas as páginas são marcadas como `noindex` para que sua cópia não concorra com o bentopdf.com nos resultados de busca. Defina como `true` para permitir a indexação pelos mecanismos de busca. | `false` |
|
||||
| `COMPRESSION_MODE` | Cópias pré-comprimidas salvas ao lado de cada arquivo: `o` nenhuma, `g` `.gz` (servidas pelo nginx da imagem), `b` `.br`, `all` ambas. O nginx da imagem não consegue servir `.br`. | `o` |
|
||||
|
||||
As URLs dos módulos WASM vêm pré-configuradas com padrões de CDN, então todos os recursos avançados funcionam sem configuração. Substitua-as em implantações isoladas da internet (air-gapped) ou hospedadas por conta própria.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Пропускать запрос числа звёзд GitHub при загрузке страницы и убирать `api.github.com` из CSP. Сборки Simple Mode всегда его пропускают. | `false` |
|
||||
| `SITE_URL` | Публичный URL, записываемый в canonical, hreflang и ссылки sitemap. Оставьте значение по умолчанию, если не хотите, чтобы поисковые системы считали ваше развёртывание отдельным сайтом. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | При собственном `SITE_URL` каждая страница помечается `noindex`, чтобы ваша копия не конкурировала с bentopdf.com в поисковой выдаче. Задайте `true`, чтобы разрешить индексацию. | `false` |
|
||||
| `COMPRESSION_MODE` | Заранее сжатые копии рядом с каждым файлом: `o` нет, `g` `.gz` (их отдаёт nginx образа), `b` `.br`, `all` обе. Nginx образа не умеет отдавать `.br`. | `o` |
|
||||
|
||||
URL модулей WASM заранее настроены на значения CDN по умолчанию, поэтому все расширенные функции работают сразу. Переопределите их для изолированных (air-gapped) или самостоятельно размещаемых развёртываний.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Skip the GitHub star-count fetch on page load and drop `api.github.com` from the CSP. Simple Mode builds always skip it. | `false` |
|
||||
| `SITE_URL` | Public URL written into canonical, hreflang and sitemap links. Leave it at the default unless you want search engines to treat your deployment as its own site. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | With a custom `SITE_URL`, every page is marked `noindex` so your copy doesn't compete with bentopdf.com in search results. Set to `true` to let search engines index it. | `false` |
|
||||
| `COMPRESSION_MODE` | Precompressed copies to add: `o` none, `g` `.gz` (served by the image's nginx), `b` `.br`, `all` both. The image's nginx can't serve `.br`. | `o` |
|
||||
|
||||
WASM module URLs are pre-configured with CDN defaults — all advanced features work out of the box. Override these for air-gapped or self-hosted deployments.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Vynechá získanie počtu hviezdičiek GitHub pri načítaní stránky a odstráni `api.github.com` z CSP. Zostavenia Simple Mode ho vynechávajú vždy. | `false` |
|
||||
| `SITE_URL` | Verejná URL zapísaná do odkazov canonical, hreflang a sitemap. Nechajte predvolenú hodnotu, pokiaľ nechcete, aby vyhľadávače považovali vaše nasadenie za samostatnú stránku. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | S vlastnou `SITE_URL` je každá stránka označená `noindex`, aby vaša kópia nekonkurovala bentopdf.com vo výsledkoch vyhľadávania. Nastavte na `true`, ak ju majú vyhľadávače indexovať. | `false` |
|
||||
| `COMPRESSION_MODE` | Predkomprimované kópie uložené vedľa každého súboru: `o` žiadne, `g` `.gz` (servíruje ich nginx v obraze), `b` `.br`, `all` obe. Nginx v obraze nevie servírovať `.br`. | `o` |
|
||||
|
||||
URL WASM modulov sú vopred nastavené na predvolené CDN, takže všetky pokročilé funkcie fungujú hneď. Pri izolovaných (air-gapped) alebo vlastných nasadeniach ich prepíšte.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Hoppa över hämtningen av GitHub-stjärnor vid sidladdning och ta bort `api.github.com` från CSP. Simple Mode-byggen hoppar alltid över den. | `false` |
|
||||
| `SITE_URL` | Publik URL som skrivs in i canonical-, hreflang- och sitemap-länkar. Behåll standardvärdet om du inte vill att sökmotorer ska behandla din driftsättning som en egen webbplats. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Med en egen `SITE_URL` markeras varje sida `noindex` så att din kopia inte konkurrerar med bentopdf.com i sökresultaten. Sätt till `true` för att låta sökmotorer indexera den. | `false` |
|
||||
| `COMPRESSION_MODE` | Förkomprimerade kopior som sparas bredvid varje fil: `o` inga, `g` `.gz` (serveras av imagens nginx), `b` `.br`, `all` båda. Imagens nginx kan inte servera `.br`. | `o` |
|
||||
|
||||
WASM-modulernas URL:er är förkonfigurerade med CDN-standardvärden, så alla avancerade funktioner fungerar direkt. Åsidosätt dem för luftgappade eller självhostade driftsättningar.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Sayfa yüklenirken GitHub yıldız sayısı çekimini atlar ve `api.github.com` adresini CSP'den çıkarır. Simple Mode derlemeleri bunu her zaman atlar. | `false` |
|
||||
| `SITE_URL` | Canonical, hreflang ve sitemap bağlantılarına yazılan herkese açık URL. Arama motorlarının dağıtımınızı ayrı bir site olarak görmesini istemiyorsanız varsayılan değerde bırakın. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Özel bir `SITE_URL` ile her sayfa `noindex` olarak işaretlenir, böylece kopyanız arama sonuçlarında bentopdf.com ile rekabet etmez. Arama motorlarının dizinlemesine izin vermek için `true` yapın. | `false` |
|
||||
| `COMPRESSION_MODE` | Her dosyanın yanına kaydedilen önceden sıkıştırılmış kopyalar: `o` yok, `g` `.gz` (imajdaki nginx sunar), `b` `.br`, `all` ikisi de. İmajdaki nginx `.br` sunamaz. | `o` |
|
||||
|
||||
WASM modül URL'leri CDN varsayılanlarıyla önceden yapılandırılmıştır, tüm gelişmiş özellikler kutudan çıktığı gibi çalışır. İnternetten yalıtılmış veya kendi sunucunuzdaki dağıtımlar için bunları geçersiz kılın.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Пропустити отримання кількості зірок GitHub під час завантаження сторінки та прибрати `api.github.com` із CSP. Збірки Simple Mode завжди це пропускають. | `false` |
|
||||
| `SITE_URL` | Публічний URL, що записується в canonical, hreflang і посилання sitemap. Залиште типовим, якщо не хочете, щоб пошукові системи сприймали ваше розгортання як окремий сайт. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Із власним `SITE_URL` кожну сторінку позначено `noindex`, щоб ваша копія не конкурувала з bentopdf.com у пошуку. Задайте `true`, щоб дозволити пошуковим системам її індексувати. | `false` |
|
||||
| `COMPRESSION_MODE` | Попередньо стиснені копії поруч із кожним файлом: `o` немає, `g` `.gz` (їх віддає nginx образу), `b` `.br`, `all` обидві. Nginx образу не вміє віддавати `.br`. | `o` |
|
||||
|
||||
URL модулів WASM попередньо налаштовано з типовими значеннями CDN, тому всі розширені функції працюють одразу. Перевизначте їх для ізольованих (air-gapped) або самостійно розгорнутих середовищ.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | Bỏ qua việc lấy số sao GitHub khi tải trang và loại `api.github.com` khỏi CSP. Các bản build Simple Mode luôn bỏ qua. | `false` |
|
||||
| `SITE_URL` | URL công khai được ghi vào các liên kết canonical, hreflang và sitemap. Hãy giữ mặc định trừ khi bạn muốn công cụ tìm kiếm coi bản triển khai của bạn là một trang riêng. | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | Với `SITE_URL` tùy chỉnh, mọi trang được đánh dấu `noindex` để bản của bạn không cạnh tranh với bentopdf.com trong kết quả tìm kiếm. Đặt `true` để cho phép công cụ tìm kiếm lập chỉ mục. | `false` |
|
||||
| `COMPRESSION_MODE` | Bản nén sẵn lưu cạnh mỗi tệp: `o` không có, `g` `.gz` (do nginx trong image phục vụ), `b` `.br`, `all` cả hai. Nginx trong image không phục vụ được `.br`. | `o` |
|
||||
|
||||
URL các module WASM đã được cấu hình sẵn với CDN mặc định, nên mọi tính năng nâng cao hoạt động ngay. Hãy ghi đè các URL này cho môi trường air-gapped hoặc tự lưu trữ.
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | 頁面載入時略過擷取 GitHub 星星數,並從 CSP 移除 `api.github.com`。Simple Mode 建置一律略過。 | `false` |
|
||||
| `SITE_URL` | 寫入 canonical、hreflang 與 sitemap 連結的公開 URL。除非您希望搜尋引擎將您的部署視為獨立網站,否則請保留預設值。 | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | 使用自訂 `SITE_URL` 時,每個頁面都會標記為 `noindex`,避免您的副本在搜尋結果中與 bentopdf.com 競爭。設為 `true` 可讓搜尋引擎建立索引。 | `false` |
|
||||
| `COMPRESSION_MODE` | 要儲存的預先壓縮副本:`o` 不儲存,`g` `.gz`(由映像檔內的 nginx 提供),`b` `.br`,`all` 兩者皆儲存。映像檔內的 nginx 無法提供 `.br`。 | `o` |
|
||||
|
||||
WASM 模組 URL 已預先設定為 CDN 預設值,所有進階功能開箱即用。離線隔離或自行架設的部署可覆寫這些值。
|
||||
|
||||
|
||||
@@ -77,14 +77,19 @@ podman-compose up -d
|
||||
# Dockerfile
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
ENV HUSKY=0
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM nginxinc/nginx-unprivileged:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY --from=builder /app/security-headers.conf /etc/nginx/security-headers.conf
|
||||
COPY --from=builder /app/security-headers-docs.conf /etc/nginx/security-headers-docs.conf
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
RUN mkdir -p /etc/nginx/tmp
|
||||
EXPOSE 8080
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
@@ -118,6 +123,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `DISABLE_GITHUB_STARS` | 页面加载时跳过获取 GitHub star 数量,并从 CSP 中移除 `api.github.com`。Simple Mode 构建始终会跳过。 | `false` |
|
||||
| `SITE_URL` | 写入 canonical、hreflang 和站点地图链接的公开 URL。除非您希望搜索引擎将您的部署视为独立站点,否则请保持默认值。 | `https://www.bentopdf.com` |
|
||||
| `ALLOW_INDEXING` | 使用自定义 `SITE_URL` 时,每个页面都会被标记为 `noindex`,以免您的副本在搜索结果中与 bentopdf.com 竞争。设为 `true` 可允许搜索引擎索引。 | `false` |
|
||||
| `COMPRESSION_MODE` | 要保存的预压缩副本:`o` 不保存,`g` `.gz`(由镜像内的 nginx 提供),`b` `.br`,`all` 两者都保存。镜像内的 nginx 无法提供 `.br`。 | `o` |
|
||||
|
||||
WASM 模块 URL 已预先配置了 CDN 默认值,所有高级功能开箱即用。对于离线隔离或自托管部署,请覆盖这些值。
|
||||
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ if [ "$DISABLE_IPV6" = "true" ]; then
|
||||
fi
|
||||
|
||||
if [ "${ROBOTS_NOINDEX:-false}" = "true" ] && [ -x /usr/local/bin/bentopdf-noindex.sh ]; then
|
||||
NOINDEX_HTML_ROOT=/usr/share/nginx/html /usr/local/bin/bentopdf-noindex.sh || true
|
||||
/usr/local/bin/bentopdf-noindex.sh
|
||||
fi
|
||||
|
||||
exec su-exec "$PUID:$PGID" "$@"
|
||||
|
||||
+5
-26
@@ -8,34 +8,13 @@ entrypoint_log() {
|
||||
fi
|
||||
}
|
||||
|
||||
NOINDEX_CONF=/etc/nginx/tmp/noindex.conf
|
||||
|
||||
if [ "${ROBOTS_NOINDEX:-false}" != "true" ]; then
|
||||
rm -f "$NOINDEX_CONF"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ROOT="${NOINDEX_HTML_ROOT:-/usr/share/nginx/html}"
|
||||
MARKER='<!-- bentopdf-noindex-injected -->'
|
||||
META_TAG='<meta name="robots" content="noindex, follow">'
|
||||
printf '%s\n' 'add_header X-Robots-Tag "noindex, follow" always;' > "$NOINDEX_CONF"
|
||||
|
||||
entrypoint_log "ROBOTS_NOINDEX=true: injecting noindex meta into HTML under $ROOT"
|
||||
|
||||
if [ ! -d "$ROOT" ]; then
|
||||
entrypoint_log "WARNING: $ROOT not found; skipping noindex injection"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
find "$ROOT" -type f -name '*.html' | while read -r file; do
|
||||
if grep -q "$MARKER" "$file"; then
|
||||
continue
|
||||
fi
|
||||
if grep -q '<meta name="robots" content="noindex' "$file"; then
|
||||
sed -i "1a\\
|
||||
$MARKER
|
||||
" "$file"
|
||||
continue
|
||||
fi
|
||||
sed -i "s|</head>| $META_TAG\\
|
||||
$MARKER\\
|
||||
</head>|" "$file"
|
||||
done
|
||||
|
||||
entrypoint_log "ROBOTS_NOINDEX: injected meta into HTML files"
|
||||
entrypoint_log "ROBOTS_NOINDEX=true: sending X-Robots-Tag: noindex, follow"
|
||||
|
||||
@@ -28,6 +28,7 @@ http {
|
||||
absolute_redirect off;
|
||||
|
||||
include /etc/nginx/security-headers.conf;
|
||||
include /etc/nginx/tmp/noindex*.conf;
|
||||
|
||||
|
||||
location ^~ /pdfjs-viewer/ {
|
||||
@@ -136,6 +137,7 @@ http {
|
||||
add_header Content-Encoding gzip;
|
||||
add_header Vary "Accept-Encoding";
|
||||
include /etc/nginx/security-headers.conf;
|
||||
include /etc/nginx/tmp/noindex*.conf;
|
||||
expires 1y;
|
||||
}
|
||||
|
||||
@@ -145,6 +147,7 @@ http {
|
||||
add_header Content-Encoding gzip;
|
||||
add_header Vary "Accept-Encoding";
|
||||
include /etc/nginx/security-headers.conf;
|
||||
include /etc/nginx/tmp/noindex*.conf;
|
||||
expires 1y;
|
||||
}
|
||||
|
||||
@@ -176,12 +179,14 @@ http {
|
||||
|
||||
location = /docs {
|
||||
include /etc/nginx/security-headers-docs.conf;
|
||||
include /etc/nginx/tmp/noindex*.conf;
|
||||
try_files /docs/index.html =404;
|
||||
expires 5m;
|
||||
}
|
||||
|
||||
location ^~ /docs/ {
|
||||
include /etc/nginx/security-headers-docs.conf;
|
||||
include /etc/nginx/tmp/noindex*.conf;
|
||||
try_files $uri $uri.html $uri/index.html /docs/index.html =404;
|
||||
expires 5m;
|
||||
}
|
||||
|
||||
Generated
-87
@@ -109,7 +109,6 @@
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.56.1",
|
||||
"vite": "^8.3.5",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-handlebars": "^2.0.0",
|
||||
"vite-plugin-node-polyfills": "^0.26.0",
|
||||
"vitepress": "^1.6.4",
|
||||
@@ -4959,39 +4958,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk/node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/character-entities-html4": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
|
||||
@@ -6829,21 +6795,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
|
||||
"integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
@@ -7830,19 +7781,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
||||
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jspdf": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.1.tgz",
|
||||
@@ -11556,16 +11494,6 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
@@ -11755,21 +11683,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-compression": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz",
|
||||
"integrity": "sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"debug": "^4.3.3",
|
||||
"fs-extra": "^10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": ">=2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-handlebars": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-handlebars/-/vite-plugin-handlebars-2.0.3.tgz",
|
||||
|
||||
+2
-3
@@ -7,9 +7,9 @@
|
||||
"scripts": {
|
||||
"predev": "node scripts/generate-blog.mjs && node scripts/generate-static-tool-links.mjs",
|
||||
"dev": "vite",
|
||||
"build": "node scripts/generate-blog.mjs && node scripts/generate-static-tool-links.mjs && tsc && vite build && node scripts/enhance-seo-pages.mjs && NODE_OPTIONS='--max-old-space-size=3072' node scripts/generate-i18n-pages.mjs && node scripts/generate-sitemap.mjs && node scripts/generate-security-headers.mjs && node scripts/apply-indexing-policy.mjs && node scripts/recompress-html.mjs && node scripts/seo-audit.mjs",
|
||||
"build": "node scripts/generate-blog.mjs && node scripts/generate-static-tool-links.mjs && tsc && vite build && node scripts/enhance-seo-pages.mjs && NODE_OPTIONS='--max-old-space-size=3072' node scripts/generate-i18n-pages.mjs && node scripts/generate-sitemap.mjs && node scripts/generate-security-headers.mjs && node scripts/apply-indexing-policy.mjs && node scripts/compress-static-assets.mjs && node scripts/seo-audit.mjs",
|
||||
"seo-audit": "node scripts/seo-audit.mjs",
|
||||
"build:with-docs": "INCLUDE_DOCS=true npm run build && npm run docs:build && node scripts/include-docs-in-dist.js && node scripts/apply-indexing-policy.mjs && node scripts/recompress-html.mjs",
|
||||
"build:with-docs": "INCLUDE_DOCS=true npm run build && npm run docs:build && node scripts/include-docs-in-dist.js && node scripts/apply-indexing-policy.mjs && node scripts/compress-static-assets.mjs",
|
||||
"build:gzip": "COMPRESSION_MODE=g npm run build",
|
||||
"build:brotli": "COMPRESSION_MODE=b npm run build",
|
||||
"build:original": "COMPRESSION_MODE=o npm run build",
|
||||
@@ -66,7 +66,6 @@
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.56.1",
|
||||
"vite": "^8.3.5",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-handlebars": "^2.0.0",
|
||||
"vite-plugin-node-polyfills": "^0.26.0",
|
||||
"vitepress": "^1.6.4",
|
||||
|
||||
@@ -1,220 +1,74 @@
|
||||
#!/usr/bin/env node
|
||||
import { createReadStream, createWriteStream, readdirSync, statSync, unlinkSync } from 'fs';
|
||||
import { join, extname } from 'path';
|
||||
import { createBrotliCompress, createGzip, constants } from 'zlib';
|
||||
import { pipeline } from 'stream/promises';
|
||||
|
||||
const DIST_DIR = './dist';
|
||||
|
||||
// File extensions to compress
|
||||
const EXTENSIONS_TO_COMPRESS = [
|
||||
'.wasm',
|
||||
'.whl',
|
||||
'.data',
|
||||
'.zip',
|
||||
'.json'
|
||||
];
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import zlib from 'zlib';
|
||||
import { promisify } from 'util';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const DIST_DIR = path.resolve(__dirname, '../dist');
|
||||
const COMPRESSIBLE = /\.(html|js|mjs|css|json|svg|wasm|xml|txt|webmanifest)$/i;
|
||||
const MIN_SIZE = 1024;
|
||||
const MODES = { o: [], g: ['.gz'], b: ['.br'], all: ['.gz', '.br'] };
|
||||
|
||||
const mode = process.env.COMPRESSION_MODE || process.argv[2] || 'all';
|
||||
const brotli = promisify(zlib.brotliCompress);
|
||||
const gzip = promisify(zlib.gzip);
|
||||
const ENCODERS = {
|
||||
'.gz': (data) => gzip(data, { level: 9 }),
|
||||
'.br': (data) =>
|
||||
brotli(data, {
|
||||
params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 11 },
|
||||
}),
|
||||
};
|
||||
|
||||
const VALID_MODES = ['g', 'b', 'o', 'all'];
|
||||
if (!VALID_MODES.includes(mode)) {
|
||||
console.error(`❌ Invalid compression mode: ${mode}`);
|
||||
console.error(` Valid modes: g (gzip only), b (brotli only), o (original only), all (all formats)`);
|
||||
process.exit(1);
|
||||
const mode = process.env.COMPRESSION_MODE || 'o';
|
||||
if (!MODES[mode]) {
|
||||
console.error(
|
||||
`Invalid COMPRESSION_MODE "${mode}". Use o (none), g (.gz), b (.br) or all (.gz and .br).`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`🔧 Compression mode: ${mode}`);
|
||||
console.log(` ${getModeDescription(mode)}\n`);
|
||||
|
||||
function getModeDescription(mode) {
|
||||
const descriptions = {
|
||||
g: 'gzip ONLY (keeps .gz, deletes originals and .br)',
|
||||
b: 'brotli ONLY (keeps .br, deletes originals and .gz)',
|
||||
o: 'original ONLY (keeps originals, deletes .gz and .br)',
|
||||
all: 'ALL formats (keeps .gz, .br, and originals)'
|
||||
};
|
||||
return descriptions[mode];
|
||||
function listFiles(dir) {
|
||||
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) return listFiles(full);
|
||||
return entry.isFile() ? [full] : [];
|
||||
});
|
||||
}
|
||||
|
||||
function getAllFiles(dir, files = []) {
|
||||
const entries = readdirSync(dir);
|
||||
const queue = MODES[mode].length
|
||||
? listFiles(DIST_DIR).filter(
|
||||
(file) => COMPRESSIBLE.test(file) && fs.statSync(file).size >= MIN_SIZE
|
||||
)
|
||||
: [];
|
||||
let written = 0;
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(dir, entry);
|
||||
const stat = statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
getAllFiles(fullPath, files);
|
||||
} else {
|
||||
files.push(fullPath);
|
||||
}
|
||||
async function compress(file) {
|
||||
const { mtimeMs } = fs.statSync(file);
|
||||
const stale = MODES[mode].filter((ext) => {
|
||||
const copy = `${file}${ext}`;
|
||||
return !fs.existsSync(copy) || fs.statSync(copy).mtimeMs < mtimeMs;
|
||||
});
|
||||
if (!stale.length) return;
|
||||
const data = await fs.promises.readFile(file);
|
||||
for (const ext of stale) {
|
||||
const encoded = await ENCODERS[ext](data);
|
||||
if (encoded.length < data.length) {
|
||||
await fs.promises.writeFile(`${file}${ext}`, encoded);
|
||||
written++;
|
||||
} else {
|
||||
fs.rmSync(`${file}${ext}`, { force: true });
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress a file with Brotli (level 11)
|
||||
*/
|
||||
async function compressBrotli(inputPath, outputPath) {
|
||||
const brotli = createBrotliCompress({
|
||||
params: {
|
||||
[constants.BROTLI_PARAM_QUALITY]: 11,
|
||||
[constants.BROTLI_PARAM_MODE]: constants.BROTLI_MODE_GENERIC,
|
||||
},
|
||||
});
|
||||
|
||||
await pipeline(
|
||||
createReadStream(inputPath),
|
||||
brotli,
|
||||
createWriteStream(outputPath)
|
||||
);
|
||||
async function worker() {
|
||||
for (let file = queue.pop(); file; file = queue.pop()) {
|
||||
await compress(file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress a file with gzip (level 9)
|
||||
*/
|
||||
async function compressGzip(inputPath, outputPath) {
|
||||
const gzip = createGzip({ level: 9 });
|
||||
await Promise.all(Array.from({ length: os.availableParallelism() }, worker));
|
||||
|
||||
await pipeline(
|
||||
createReadStream(inputPath),
|
||||
gzip,
|
||||
createWriteStream(outputPath)
|
||||
);
|
||||
}
|
||||
|
||||
function deleteCompressedFiles() {
|
||||
console.log('🗑️ Deleting compressed files...\n');
|
||||
const allFiles = getAllFiles(DIST_DIR);
|
||||
let deletedCount = 0;
|
||||
|
||||
for (const file of allFiles) {
|
||||
if (file.endsWith('.br') || file.endsWith('.gz')) {
|
||||
unlinkSync(file);
|
||||
deletedCount++;
|
||||
console.log(` Deleted: ${file}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n✅ Deleted ${deletedCount} compressed files\n`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete original files (keep only compressed versions)
|
||||
*/
|
||||
function deleteOriginalFiles(filePaths, extension) {
|
||||
console.log(`🗑️ Deleting original files (keeping only ${extension})...\n`);
|
||||
let deletedCount = 0;
|
||||
|
||||
for (const file of filePaths) {
|
||||
try {
|
||||
unlinkSync(file);
|
||||
deletedCount++;
|
||||
console.log(` Deleted: ${file}`);
|
||||
} catch (error) {
|
||||
console.error(` ⚠️ Failed to delete ${file}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n✅ Deleted ${deletedCount} original files\n`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete specific compressed format
|
||||
*/
|
||||
function deleteCompressedFormat(extension) {
|
||||
console.log(`🗑️ Deleting ${extension} files...\n`);
|
||||
const allFiles = getAllFiles(DIST_DIR);
|
||||
let deletedCount = 0;
|
||||
|
||||
for (const file of allFiles) {
|
||||
if (file.endsWith(extension)) {
|
||||
unlinkSync(file);
|
||||
deletedCount++;
|
||||
console.log(` Deleted: ${file}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n✅ Deleted ${deletedCount} ${extension} files\n`);
|
||||
}
|
||||
|
||||
async function compressStaticAssets() {
|
||||
if (mode === 'o') {
|
||||
deleteCompressedFiles();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🔍 Scanning for static assets to compress...\n');
|
||||
|
||||
const allFiles = getAllFiles(DIST_DIR);
|
||||
const filesToCompress = allFiles.filter(file => {
|
||||
const ext = extname(file);
|
||||
const stat = statSync(file);
|
||||
|
||||
if (file.endsWith('.br') || file.endsWith('.gz')) {
|
||||
return false;
|
||||
}
|
||||
return EXTENSIONS_TO_COMPRESS.includes(ext) && stat.size >= MIN_SIZE;
|
||||
});
|
||||
|
||||
console.log(`📦 Found ${filesToCompress.length} files to compress\n`);
|
||||
|
||||
let processedCount = 0;
|
||||
const shouldCompressBrotli = mode === 'b' || mode === 'all';
|
||||
const shouldCompressGzip = mode === 'g' || mode === 'all';
|
||||
|
||||
for (const file of filesToCompress) {
|
||||
const stat = statSync(file);
|
||||
const sizeMB = (stat.size / (1024 * 1024)).toFixed(2);
|
||||
|
||||
try {
|
||||
let brotliStat, gzipStat;
|
||||
|
||||
if (shouldCompressBrotli) {
|
||||
await compressBrotli(file, `${file}.br`);
|
||||
brotliStat = statSync(`${file}.br`);
|
||||
}
|
||||
if (shouldCompressGzip) {
|
||||
await compressGzip(file, `${file}.gz`);
|
||||
gzipStat = statSync(`${file}.gz`);
|
||||
}
|
||||
|
||||
processedCount++;
|
||||
console.log(`✅ ${file}`);
|
||||
console.log(` Original: ${sizeMB} MB`);
|
||||
|
||||
if (brotliStat) {
|
||||
const brotliSizeMB = (brotliStat.size / (1024 * 1024)).toFixed(2);
|
||||
console.log(` Brotli: ${brotliSizeMB} MB (${((brotliStat.size / stat.size) * 100).toFixed(1)}%)`);
|
||||
}
|
||||
|
||||
if (gzipStat) {
|
||||
const gzipSizeMB = (gzipStat.size / (1024 * 1024)).toFixed(2);
|
||||
console.log(` Gzip: ${gzipSizeMB} MB (${((gzipStat.size / stat.size) * 100).toFixed(1)}%)`);
|
||||
}
|
||||
|
||||
console.log('');
|
||||
} catch (error) {
|
||||
console.error(`❌ Failed to compress ${file}:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n🎉 Compressed ${processedCount}/${filesToCompress.length} files successfully!\n`);
|
||||
|
||||
if (mode === 'g') {
|
||||
deleteCompressedFormat('.br');
|
||||
deleteOriginalFiles(filesToCompress, '.gz');
|
||||
} else if (mode === 'b') {
|
||||
deleteCompressedFormat('.gz');
|
||||
deleteOriginalFiles(filesToCompress, '.br');
|
||||
}
|
||||
}
|
||||
|
||||
compressStaticAssets().catch(err => {
|
||||
console.error('❌ Compression failed:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
console.log(`Compression mode ${mode}: wrote ${written} precompressed files.`);
|
||||
|
||||
@@ -181,7 +181,7 @@ OPTIONS:
|
||||
--dockerfile <path> Dockerfile to use (default: Dockerfile)
|
||||
--simple-mode Enable Simple Mode
|
||||
--base-url <path> Subdirectory base URL (e.g. /pdf/)
|
||||
--compression <mode> Compression: g, b, o, all (default: all)
|
||||
--compression <mode> Compression: g, b, o, all (default: o)
|
||||
--language <code> Default UI language (e.g. fr, de, es)
|
||||
--brand-name <name> Custom brand name
|
||||
--brand-logo <path> Logo path relative to public/
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import zlib from 'zlib';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const DIST_DIR = path.resolve(__dirname, '../dist');
|
||||
|
||||
function listHtml(dir) {
|
||||
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) return listHtml(full);
|
||||
return entry.name.endsWith('.html') ? [full] : [];
|
||||
});
|
||||
}
|
||||
|
||||
let refreshed = 0;
|
||||
for (const file of listHtml(DIST_DIR)) {
|
||||
const brotli = `${file}.br`;
|
||||
const gzip = `${file}.gz`;
|
||||
if (!fs.existsSync(brotli) && !fs.existsSync(gzip)) continue;
|
||||
const html = fs.readFileSync(file);
|
||||
if (fs.existsSync(brotli)) {
|
||||
fs.writeFileSync(
|
||||
brotli,
|
||||
zlib.brotliCompressSync(html, {
|
||||
params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 11 },
|
||||
})
|
||||
);
|
||||
}
|
||||
if (fs.existsSync(gzip)) {
|
||||
fs.writeFileSync(gzip, zlib.gzipSync(html, { level: 9 }));
|
||||
}
|
||||
refreshed++;
|
||||
}
|
||||
console.log(`Recompressed ${refreshed} precompressed HTML files.`);
|
||||
@@ -6,11 +6,9 @@ import type { Connect, Plugin } from 'vite';
|
||||
// import basicSsl from '@vitejs/plugin-basic-ssl';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import { nodePolyfills } from 'vite-plugin-node-polyfills';
|
||||
import viteCompression from 'vite-plugin-compression';
|
||||
import handlebars from 'vite-plugin-handlebars';
|
||||
import { resolve } from 'path';
|
||||
import fs from 'fs';
|
||||
import { constants as zlibConstants } from 'zlib';
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
function engineVersion(): string {
|
||||
@@ -727,30 +725,6 @@ export default defineConfig(({ command }) => {
|
||||
process: true,
|
||||
},
|
||||
}),
|
||||
viteCompression({
|
||||
algorithm: 'brotliCompress',
|
||||
ext: '.br',
|
||||
threshold: 1024,
|
||||
filter: /\.(js|mjs|json|css|html|wasm|svg)$/i,
|
||||
compressionOptions: {
|
||||
params: {
|
||||
[zlibConstants.BROTLI_PARAM_QUALITY]: 11,
|
||||
[zlibConstants.BROTLI_PARAM_MODE]:
|
||||
zlibConstants.BROTLI_MODE_GENERIC,
|
||||
},
|
||||
},
|
||||
deleteOriginFile: false,
|
||||
}),
|
||||
viteCompression({
|
||||
algorithm: 'gzip',
|
||||
ext: '.gz',
|
||||
threshold: 1024,
|
||||
filter: /\.(js|mjs|json|css|html|wasm|svg)$/i,
|
||||
compressionOptions: {
|
||||
level: 9,
|
||||
},
|
||||
deleteOriginFile: false,
|
||||
}),
|
||||
],
|
||||
define: {
|
||||
__SIMPLE_MODE__: JSON.stringify(process.env.SIMPLE_MODE === 'true'),
|
||||
|
||||
Reference in New Issue
Block a user