nuxt-og-image 0.4.0 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +66 -35
- package/dist/runtime/browserService.d.ts +1 -1
- package/dist/runtime/browserService.mjs +32 -9
- package/dist/runtime/nitro/image.mjs +3 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -39,11 +39,23 @@ Generate dynamic social share images for you Nuxt v3 app.
|
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
41
|
npm install --save-dev nuxt-og-image
|
|
42
|
-
|
|
43
42
|
# Using yarn
|
|
44
43
|
yarn add --dev nuxt-og-image
|
|
45
44
|
```
|
|
46
45
|
|
|
46
|
+
### Chromium Dependency
|
|
47
|
+
|
|
48
|
+
By default, this module does not install chromium binaries for you, instead relying on locally
|
|
49
|
+
installed chrome.
|
|
50
|
+
|
|
51
|
+
If you want to use this module in a CI or SSR environment, you will need the binaries.
|
|
52
|
+
|
|
53
|
+
You can either use `puppeteer` or `chrome-aws-lambda`.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install --save-dev puppeteer # or chrome-aws-lambda
|
|
57
|
+
```
|
|
58
|
+
|
|
47
59
|
## Setup
|
|
48
60
|
|
|
49
61
|
_nuxt.config.ts_
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFile, writeFile, rm, mkdir } from 'node:fs/promises';
|
|
2
2
|
import { defineNuxtModule, createResolver, addTemplate, getNuxtVersion, addServerHandler, addImports, addComponent } from '@nuxt/kit';
|
|
3
3
|
import { execa } from 'execa';
|
|
4
4
|
import { hash } from 'ohash';
|
|
@@ -10,15 +10,38 @@ import fg from 'fast-glob';
|
|
|
10
10
|
import { join } from 'pathe';
|
|
11
11
|
|
|
12
12
|
async function createBrowser() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
try {
|
|
14
|
+
const playwrightCore = await import('playwright-core');
|
|
15
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = process.env.AWS_LAMBDA_FUNCTION_NAME || "RUNTIME_HACK";
|
|
16
|
+
const awsChrome = await import(String("chrome-aws-lambda"));
|
|
17
|
+
return await playwrightCore.chromium.launch({
|
|
18
|
+
args: awsChrome.args,
|
|
19
|
+
executablePath: await awsChrome.executablePath,
|
|
20
|
+
headless: awsChrome.headless
|
|
21
|
+
});
|
|
22
|
+
} catch (e) {
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const playwrightCore = await import('playwright-core');
|
|
26
|
+
const { Launcher } = await import('chrome-launcher');
|
|
27
|
+
const chromePath = Launcher.getFirstInstallation();
|
|
28
|
+
return await playwrightCore.chromium.launch({
|
|
29
|
+
headless: true,
|
|
30
|
+
executablePath: chromePath
|
|
31
|
+
});
|
|
32
|
+
} catch (e) {
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const playwright = await import(String("playwright"));
|
|
36
|
+
return await playwright.chromium.launch({
|
|
37
|
+
headless: true
|
|
38
|
+
});
|
|
39
|
+
} catch (e) {
|
|
40
|
+
throw new Error(`
|
|
41
|
+
Missing chromium binary. You need either 'playwright' or 'chrome-aws-lambda'.
|
|
42
|
+
Please run 'yarn add --dev playwright' or 'npm install --save-dev playwright'
|
|
43
|
+
`);
|
|
44
|
+
}
|
|
22
45
|
}
|
|
23
46
|
async function screenshot(browser, url, options) {
|
|
24
47
|
const page = await browser.newPage({
|
|
@@ -131,6 +154,7 @@ declare module 'nitropack' {
|
|
|
131
154
|
});
|
|
132
155
|
nuxt.hooks.hook("nitro:init", async (nitro) => {
|
|
133
156
|
let entries = [];
|
|
157
|
+
let cleanupEntries = [];
|
|
134
158
|
const _routeRulesMatcher = toRouteMatcher(
|
|
135
159
|
createRouter({ routes: nitro.options.routeRules })
|
|
136
160
|
);
|
|
@@ -184,22 +208,24 @@ declare module 'nitropack' {
|
|
|
184
208
|
});
|
|
185
209
|
})).trim();
|
|
186
210
|
browser = await createBrowser();
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
211
|
+
if (browser) {
|
|
212
|
+
nitro.logger.info(`Generating ${entries.length} og:images...`);
|
|
213
|
+
for (const k in entries) {
|
|
214
|
+
const entry = entries[k];
|
|
215
|
+
const start = Date.now();
|
|
216
|
+
let hasError = false;
|
|
217
|
+
try {
|
|
218
|
+
const imgBuffer = await screenshot(browser, `${host}${entry.screenshotPath}`, config);
|
|
219
|
+
await writeFile(entry.outputPath, imgBuffer);
|
|
220
|
+
} catch (e) {
|
|
221
|
+
hasError = true;
|
|
222
|
+
console.error(e);
|
|
223
|
+
}
|
|
224
|
+
const generateTimeMS = Date.now() - start;
|
|
225
|
+
nitro.logger.log(chalk[hasError ? "red" : "gray"](
|
|
226
|
+
` ${Number(k) === entries.length - 1 ? "\u2514\u2500" : "\u251C\u2500"} /${config.outputDir}/${entry.fileName} (${generateTimeMS}ms) ${Math.round(Number(k) / (entries.length - 1) * 100)}%`
|
|
227
|
+
));
|
|
198
228
|
}
|
|
199
|
-
const generateTimeMS = Date.now() - start;
|
|
200
|
-
nitro.logger.log(chalk[hasError ? "red" : "gray"](
|
|
201
|
-
` ${Number(k) === entries.length - 1 ? "\u2514\u2500" : "\u251C\u2500"} /${config.outputDir}/${entry.fileName} (${generateTimeMS}ms) ${Math.round(Number(k) / (entries.length - 1) * 100)}%`
|
|
202
|
-
));
|
|
203
229
|
}
|
|
204
230
|
} catch (e) {
|
|
205
231
|
console.error(e);
|
|
@@ -207,16 +233,7 @@ declare module 'nitropack' {
|
|
|
207
233
|
await browser?.close();
|
|
208
234
|
previewProcess.kill();
|
|
209
235
|
}
|
|
210
|
-
|
|
211
|
-
const html = await readFile(entry.linkingHtml, "utf-8");
|
|
212
|
-
const newHtml = html.replace(new RegExp(`<link id="${LinkPrerenderId}" rel="prerender" href="(.*?)">`), "").replace(new RegExp(`<script id="${PayloadScriptId}" type="application/json">(.*?)<\/script>`), "").replace("\n\n", "\n");
|
|
213
|
-
if (html !== newHtml) {
|
|
214
|
-
await writeFile(entry.linkingHtml, newHtml, { encoding: "utf-8" });
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const ogImageFolders = await fg([`**/${HtmlRendererRoute}`], { cwd: nitro.options.output.publicDir, onlyDirectories: true });
|
|
218
|
-
for (const ogImageFolder of ogImageFolders)
|
|
219
|
-
await rm(join(nitro.options.output.publicDir, ogImageFolder), { recursive: true, force: true });
|
|
236
|
+
cleanupEntries = [...entries];
|
|
220
237
|
entries = [];
|
|
221
238
|
};
|
|
222
239
|
nitro.hooks.hook("rollup:before", async () => {
|
|
@@ -224,6 +241,20 @@ declare module 'nitropack' {
|
|
|
224
241
|
});
|
|
225
242
|
nitro.hooks.hook("close", async () => {
|
|
226
243
|
await outputOgImages();
|
|
244
|
+
for (const entry of cleanupEntries) {
|
|
245
|
+
try {
|
|
246
|
+
const html = await readFile(entry.linkingHtml, "utf-8");
|
|
247
|
+
const newHtml = html.replace(new RegExp(`<link id="${LinkPrerenderId}" rel="prerender" href="(.*?)">`), "").replace(new RegExp(`<script id="${PayloadScriptId}" type="application/json">(.*?)<\/script>`), "").replace("\n\n", "\n");
|
|
248
|
+
if (html !== newHtml) {
|
|
249
|
+
await writeFile(entry.linkingHtml, newHtml, { encoding: "utf-8" });
|
|
250
|
+
}
|
|
251
|
+
} catch (e) {
|
|
252
|
+
console.error(e);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const ogImageFolders = await fg([`**/${HtmlRendererRoute}`], { cwd: nitro.options.output.publicDir, onlyDirectories: true });
|
|
256
|
+
for (const ogImageFolder of ogImageFolders)
|
|
257
|
+
await rm(join(nitro.options.output.publicDir, ogImageFolder), { recursive: true, force: true });
|
|
227
258
|
});
|
|
228
259
|
});
|
|
229
260
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { Browser } from 'playwright-core';
|
|
3
3
|
import type { ScreenshotOptions } from '../types';
|
|
4
|
-
export declare function createBrowser(): Promise<
|
|
4
|
+
export declare function createBrowser(): Promise<any>;
|
|
5
5
|
export declare function screenshot(browser: Browser, url: string, options: ScreenshotOptions): Promise<Buffer>;
|
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
export async function createBrowser() {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
try {
|
|
3
|
+
const playwrightCore = await import("playwright-core");
|
|
4
|
+
process.env.AWS_LAMBDA_FUNCTION_NAME = process.env.AWS_LAMBDA_FUNCTION_NAME || "RUNTIME_HACK";
|
|
5
|
+
const awsChrome = await import(String("chrome-aws-lambda"));
|
|
6
|
+
return await playwrightCore.chromium.launch({
|
|
7
|
+
args: awsChrome.args,
|
|
8
|
+
executablePath: await awsChrome.executablePath,
|
|
9
|
+
headless: awsChrome.headless
|
|
10
|
+
});
|
|
11
|
+
} catch (e) {
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const playwrightCore = await import("playwright-core");
|
|
15
|
+
const { Launcher } = await import("chrome-launcher");
|
|
16
|
+
const chromePath = Launcher.getFirstInstallation();
|
|
17
|
+
return await playwrightCore.chromium.launch({
|
|
18
|
+
headless: true,
|
|
19
|
+
executablePath: chromePath
|
|
20
|
+
});
|
|
21
|
+
} catch (e) {
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const playwright = await import(String("playwright"));
|
|
25
|
+
return await playwright.chromium.launch({
|
|
26
|
+
headless: true
|
|
27
|
+
});
|
|
28
|
+
} catch (e) {
|
|
29
|
+
throw new Error(`
|
|
30
|
+
Missing chromium binary. You need either 'playwright' or 'chrome-aws-lambda'.
|
|
31
|
+
Please run 'yarn add --dev playwright' or 'npm install --save-dev playwright'
|
|
32
|
+
`);
|
|
33
|
+
}
|
|
11
34
|
}
|
|
12
35
|
export async function screenshot(browser, url, options) {
|
|
13
36
|
const page = await browser.newPage({
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { defineEventHandler, getRequestHeader, setHeader } from "h3";
|
|
2
2
|
import { createBrowser, screenshot } from "../browserService.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { DefaultRuntimeImageSuffix, HtmlRendererRoute } from "#nuxt-og-image/constants";
|
|
4
4
|
export default defineEventHandler(async (e) => {
|
|
5
|
-
if (!e.path?.endsWith(
|
|
5
|
+
if (!e.path?.endsWith(DefaultRuntimeImageSuffix))
|
|
6
6
|
return;
|
|
7
|
-
const path = e.path.replace(
|
|
7
|
+
const path = e.path.replace(DefaultRuntimeImageSuffix, HtmlRendererRoute);
|
|
8
8
|
const host = getRequestHeader(e, "host") || "localhost:3000";
|
|
9
9
|
const browser = await createBrowser();
|
|
10
10
|
setHeader(e, "Content-Type", "image/png");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-og-image",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.3",
|
|
5
5
|
"packageManager": "pnpm@7.8.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://github.com/sponsors/harlan-zw",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@nuxt/kit": "3.0.0",
|
|
30
30
|
"chalk": "^5.2.0",
|
|
31
|
-
"chrome-
|
|
31
|
+
"chrome-launcher": "^0.15.1",
|
|
32
32
|
"defu": "^6.1.1",
|
|
33
33
|
"execa": "^6.1.0",
|
|
34
34
|
"fast-glob": "^3.2.12",
|