@rendela/vite 0.0.1

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 ADDED
@@ -0,0 +1,115 @@
1
+ # Rendela - SPA Page Prerendering Plugin
2
+
3
+ `Rendela` is a powerful tool designed to optimize Single Page Applications (SPAs) by prerendering them for better SEO, performance, and overall user experience. It helps search engines to index your pages more effectively, improves load times, and enhances the visibility of your site.
4
+
5
+ ## Key Features
6
+ - **SEO Optimization:** Prerenders pages to ensure they are properly indexed by search engines.
7
+ - **Faster Load Times:** By prerendering pages, users get content faster on their first visit.
8
+ - **Easy Integration:** Easily integrates with your existing SPA built with frameworks like Vue, React, etc.
9
+ - **Works with Vite:** This package works seamlessly with Vite to optimize SPA performance.
10
+
11
+ ## Prerequisites
12
+
13
+ Before you start using `rendela`, you will need to install **Chromium** on your machine. This is required to properly prerender the pages as `rendela` uses Chromium in headless mode for rendering.
14
+
15
+ ### Installation for Chromium
16
+
17
+ #### On Ubuntu/Debian (Linux)
18
+
19
+ 1. First, update your package list:
20
+ ```bash
21
+ sudo apt update
22
+ ```
23
+
24
+ 2. Then, install Chromium:
25
+ ```bash
26
+ sudo apt install chromium
27
+ ```
28
+
29
+ 3. Verify the installation by running:
30
+ ```bash
31
+ chromium --version
32
+ ```
33
+
34
+ This should show the installed Chromium version.
35
+
36
+ #### On Windows
37
+
38
+ 1. **Download Chromium**: You can download the latest stable version of Chromium from the [official website](https://download-chromium.appspot.com/).
39
+
40
+ 2. **Extract the Archive**: Extract the downloaded `.zip` file to a location of your choice (e.g., `C:\Program Files\Chromium`).
41
+
42
+ 3. **Set the Path**: You need to add the path to the Chromium executable in your system’s PATH environment variable.
43
+ - Open **System Properties** > **Environment Variables**.
44
+ - Under **System Variables**, find and select `Path`, then click **Edit**.
45
+ - Click **New**, and add the path to the folder where Chromium is located (e.g., `C:\Program Files\Chromium`).
46
+
47
+ 4. Verify the installation by running the following command in a terminal or command prompt:
48
+ ```bash
49
+ chromium --version
50
+ ```
51
+
52
+ #### On macOS
53
+
54
+ 1. **Install Chromium**: You can install Chromium using Homebrew. If you don't have Homebrew installed, first install it by running:
55
+ ```bash
56
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
57
+ ```
58
+
59
+ 2. **Install Chromium** via Homebrew:
60
+ ```bash
61
+ brew install chromium
62
+ ```
63
+
64
+ 3. Verify the installation by running:
65
+ ```bash
66
+ chromium --version
67
+ ```
68
+
69
+ If you don't use Homebrew, you can manually download Chromium from the [official website](https://download-chromium.appspot.com/) and follow similar steps as for Windows.
70
+
71
+ ---
72
+
73
+ ## Installation
74
+
75
+ Once Chromium is installed on your machine, you can proceed to install `rendela` as a Vite plugin.
76
+
77
+ 1. Install the package via npm or yarn:
78
+ ```bash
79
+ npm install @rendela/vite
80
+ # or
81
+ yarn add @rendela/vite
82
+ ```
83
+
84
+ 2. Add `rendela` to your `vite.config.js`:
85
+ ```javascript
86
+ import { defineConfig } from 'vite'
87
+ import rendela from '@rendela/vite'
88
+
89
+ export default defineConfig({
90
+ plugins: [rendela()],
91
+ })
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Usage
97
+
98
+ Once you've installed and configured `rendela` with Vite, it will automatically handle prerendering of your SPA pages when you build your project.
99
+
100
+ ### How It Works
101
+ - `rendela` will use the installed Chromium instance in headless mode to render and capture your pages.
102
+ - It generates static HTML files of your pages that can be served to crawlers or users, ensuring better SEO and performance.
103
+
104
+ ---
105
+
106
+ ## Additional Notes
107
+
108
+ - Make sure your Chromium installation is accessible from your system's PATH for `rendela` to function properly.
109
+ - If you're running the plugin in a CI environment, make sure the Chromium binary is installed and available.
110
+
111
+ ---
112
+
113
+ ## License
114
+
115
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
package/dist/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # Rendela - SPA Page Prerendering Plugin
2
+
3
+ `Rendela` is a powerful tool designed to optimize Single Page Applications (SPAs) by prerendering them for better SEO, performance, and overall user experience. It helps search engines to index your pages more effectively, improves load times, and enhances the visibility of your site.
4
+
5
+ ## Key Features
6
+ - **SEO Optimization:** Prerenders pages to ensure they are properly indexed by search engines.
7
+ - **Faster Load Times:** By prerendering pages, users get content faster on their first visit.
8
+ - **Easy Integration:** Easily integrates with your existing SPA built with frameworks like Vue, React, etc.
9
+ - **Works with Vite:** This package works seamlessly with Vite to optimize SPA performance.
10
+
11
+ ## Prerequisites
12
+
13
+ Before you start using `rendela`, you will need to install **Chromium** on your machine. This is required to properly prerender the pages as `rendela` uses Chromium in headless mode for rendering.
14
+
15
+ ### Installation for Chromium
16
+
17
+ #### On Ubuntu/Debian (Linux)
18
+
19
+ 1. First, update your package list:
20
+ ```bash
21
+ sudo apt update
22
+ ```
23
+
24
+ 2. Then, install Chromium:
25
+ ```bash
26
+ sudo apt install chromium
27
+ ```
28
+
29
+ 3. Verify the installation by running:
30
+ ```bash
31
+ chromium --version
32
+ ```
33
+
34
+ This should show the installed Chromium version.
35
+
36
+ #### On Windows
37
+
38
+ 1. **Download Chromium**: You can download the latest stable version of Chromium from the [official website](https://download-chromium.appspot.com/).
39
+
40
+ 2. **Extract the Archive**: Extract the downloaded `.zip` file to a location of your choice (e.g., `C:\Program Files\Chromium`).
41
+
42
+ 3. **Set the Path**: You need to add the path to the Chromium executable in your system’s PATH environment variable.
43
+ - Open **System Properties** > **Environment Variables**.
44
+ - Under **System Variables**, find and select `Path`, then click **Edit**.
45
+ - Click **New**, and add the path to the folder where Chromium is located (e.g., `C:\Program Files\Chromium`).
46
+
47
+ 4. Verify the installation by running the following command in a terminal or command prompt:
48
+ ```bash
49
+ chromium --version
50
+ ```
51
+
52
+ #### On macOS
53
+
54
+ 1. **Install Chromium**: You can install Chromium using Homebrew. If you don't have Homebrew installed, first install it by running:
55
+ ```bash
56
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
57
+ ```
58
+
59
+ 2. **Install Chromium** via Homebrew:
60
+ ```bash
61
+ brew install chromium
62
+ ```
63
+
64
+ 3. Verify the installation by running:
65
+ ```bash
66
+ chromium --version
67
+ ```
68
+
69
+ If you don't use Homebrew, you can manually download Chromium from the [official website](https://download-chromium.appspot.com/) and follow similar steps as for Windows.
70
+
71
+ ---
72
+
73
+ ## Installation
74
+
75
+ Once Chromium is installed on your machine, you can proceed to install `rendela` as a Vite plugin.
76
+
77
+ 1. Install the package via npm or yarn:
78
+ ```bash
79
+ npm install @rendela/vite
80
+ # or
81
+ yarn add @rendela/vite
82
+ ```
83
+
84
+ 2. Add `rendela` to your `vite.config.js`:
85
+ ```javascript
86
+ import { defineConfig } from 'vite'
87
+ import rendela from '@rendela/vite'
88
+
89
+ export default defineConfig({
90
+ plugins: [rendela()],
91
+ })
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Usage
97
+
98
+ Once you've installed and configured `rendela` with Vite, it will automatically handle prerendering of your SPA pages when you build your project.
99
+
100
+ ### How It Works
101
+ - `rendela` will use the installed Chromium instance in headless mode to render and capture your pages.
102
+ - It generates static HTML files of your pages that can be served to crawlers or users, ensuring better SEO and performance.
103
+
104
+ ---
105
+
106
+ ## Additional Notes
107
+
108
+ - Make sure your Chromium installation is accessible from your system's PATH for `rendela` to function properly.
109
+ - If you're running the plugin in a CI environment, make sure the Chromium binary is installed and available.
110
+
111
+ ---
112
+
113
+ ## License
114
+
115
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
package/dist/cli.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { startServer } from './server.js';
3
+ startServer(true);
4
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,WAAW,CAAC,IAAI,CAAC,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,45 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ export const rootPath = process.cwd();
4
+ export const configFilePath = path.join(rootPath, "rendela.config.js");
5
+ export const defaultConfig = `// @ts-check
6
+ /**
7
+ * @type {import('rendela').RendelaConfigType}
8
+ */
9
+ export default {
10
+ pages: [{ url: "/" }, { url: "/signin" }, { url: "/signup" }], // list of pages to render ({url: string, filename?: string, timeout?: number})
11
+ buildDir: "dist", // application build directory
12
+ port: 3300, // port to run the server on when rendering
13
+ savePath: "pages", // path to save the rendered pages
14
+ pageWaitTime: 10, // timeout for the page to load in ms
15
+ pageTimeout: 5000, // timeout for the page to load in ms
16
+ debug: true, // enable debug mode
17
+ autoStartOnBuild: true, // auto start the server on build
18
+ concurrencyLimit: 3, // number of concurrent pages to render
19
+ };
20
+ `;
21
+ export function createDefaultConfigFile() {
22
+ if (!fs.existsSync(configFilePath)) {
23
+ fs.mkdirSync(path.dirname(configFilePath), { recursive: true });
24
+ fs.writeFileSync(configFilePath, defaultConfig, "utf-8");
25
+ return "Config file not found, creating default config";
26
+ }
27
+ return null;
28
+ }
29
+ export async function getConfig() {
30
+ const configFile = await import(configFilePath);
31
+ const loadedConfig = configFile?.default;
32
+ return {
33
+ buildDir: loadedConfig?.buildDir ?? "dist",
34
+ port: loadedConfig?.port ?? 3000,
35
+ savePath: loadedConfig?.savePath ?? "pages",
36
+ pageWaitTime: loadedConfig?.pageWaitTime ?? 0,
37
+ pageTimeout: loadedConfig?.pageTimeout ?? 0,
38
+ pages: loadedConfig?.pages ?? [{ url: "/" }],
39
+ debug: loadedConfig?.debug ?? true,
40
+ autoStartOnBuild: loadedConfig?.autoStartOnBuild ?? true,
41
+ chromiumExecutablePath: loadedConfig?.chromiumExecutablePath ?? undefined,
42
+ concurrencyLimit: loadedConfig?.concurrencyLimit ?? 3,
43
+ };
44
+ }
45
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;AACvE,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;CAe5B,CAAC;AAEF,MAAM,UAAU,uBAAuB;IACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACnC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO,gDAAgD,CAAA;IACzD,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,UAAU,EAAE,OAAO,CAAC;IACzC,OAAQ;QACN,QAAQ,EAAE,YAAY,EAAE,QAAQ,IAAI,MAAM;QAC1C,IAAI,EAAE,YAAY,EAAE,IAAI,IAAI,IAAI;QAChC,QAAQ,EAAE,YAAY,EAAE,QAAQ,IAAI,OAAO;QAC3C,YAAY,EAAE,YAAY,EAAE,YAAY,IAAI,CAAC;QAC7C,WAAW,EAAE,YAAY,EAAE,WAAW,IAAI,CAAC;QAC3C,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QAC5C,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,IAAI;QAClC,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,IAAI,IAAI;QACxD,sBAAsB,EAAE,YAAY,EAAE,sBAAsB,IAAI,SAAS;QACzE,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,IAAI,CAAC;KACtD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { chromium } from 'playwright';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { LogUtils } from './logUtils.js';
5
+ export async function startCrawler(config) {
6
+ const browser = await chromium.launch({
7
+ headless: true
8
+ });
9
+ const projectSavePath = path.join(config.buildDir, config.savePath);
10
+ const savePath = path.join(process.cwd(), projectSavePath);
11
+ if (!fs.existsSync(savePath)) {
12
+ fs.mkdirSync(savePath, { recursive: true });
13
+ }
14
+ if (config.debug) {
15
+ LogUtils.log(`✓ ${config.pages.length ?? 0} pages to crawl in ${LogUtils.startPrintingGray()}${projectSavePath}${LogUtils.endPrintingGray()}`);
16
+ }
17
+ const concurrencyLimit = config.concurrencyLimit || 3;
18
+ const pages = [...config.pages];
19
+ while (pages.length > 0) {
20
+ if (config.debug) {
21
+ LogUtils.info('');
22
+ }
23
+ const batch = pages.splice(0, concurrencyLimit);
24
+ await Promise.all(batch.map((url) => processPage(browser, config, url, savePath, projectSavePath)));
25
+ }
26
+ await browser.close();
27
+ }
28
+ async function processPage(browser, config, url, savePath, projectSavePath) {
29
+ if (!url.url.startsWith('/')) {
30
+ url.url = `/${url.url}`;
31
+ }
32
+ const html = await crawlPage(browser, config, url);
33
+ if (html) {
34
+ const fileName = url.url && url.url !== '/' ? url.url : '';
35
+ const filePath = path.join(savePath, fileName);
36
+ if (!fs.existsSync(filePath)) {
37
+ fs.mkdirSync(filePath, { recursive: true });
38
+ }
39
+ await fs.promises.writeFile(path.join(filePath, 'index.html'), html);
40
+ if (config.debug) {
41
+ const signalPreSignal = fileName[0] === '/' ? '' : '/';
42
+ const signalPostSignal = fileName === '' || fileName[fileName.length - 1] === '/' ? '' : '/';
43
+ LogUtils.info(`Crawled: ${LogUtils.startPrintingGray()}${url.url}${LogUtils.endPrintingGray()} > ${LogUtils.startPrintingGray()}${projectSavePath}${signalPreSignal}${LogUtils.endPrintingGray()}${fileName}${signalPostSignal}index.html`);
44
+ }
45
+ }
46
+ }
47
+ async function crawlPage(browser, config, pageConfig) {
48
+ const context = await browser.newContext();
49
+ const page = await context.newPage();
50
+ try {
51
+ // Block unnecessary resources
52
+ await page.route('**/*', (route) => {
53
+ const resourceType = route.request().resourceType();
54
+ if (['image', 'font', 'media'].includes(resourceType)) {
55
+ route.abort();
56
+ }
57
+ else {
58
+ route.continue();
59
+ }
60
+ });
61
+ const timeout = config?.pageWaitTime ?? 0;
62
+ if (config.pageTimeout) {
63
+ page.setDefaultNavigationTimeout(timeout + config.pageTimeout);
64
+ }
65
+ const response = await page.goto(`http://localhost:${config.port}${pageConfig.url}`, {
66
+ waitUntil: 'networkidle',
67
+ });
68
+ if (response && response.status() === 404) {
69
+ LogUtils.error(`Skipping 404: ${pageConfig.url}`);
70
+ return null;
71
+ }
72
+ await page.waitForTimeout(timeout);
73
+ const html = await page.content();
74
+ return html;
75
+ }
76
+ catch (error) {
77
+ LogUtils.error(`Error crawling ${pageConfig.url}: ${error}`);
78
+ return null;
79
+ }
80
+ finally {
81
+ await page.close();
82
+ await context.close();
83
+ }
84
+ }
85
+ //# sourceMappingURL=crawler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawler.js","sourceRoot":"","sources":["../src/crawler.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ import { startServer } from "./server.js";
2
+ export default function rendela() {
3
+ return {
4
+ name: "rendela",
5
+ apply: "build",
6
+ closeBundle() {
7
+ process.nextTick(() => {
8
+ setImmediate(() => {
9
+ startServer();
10
+ });
11
+ });
12
+ },
13
+ };
14
+ }
15
+ export * from "./server.js";
16
+ export * from "./config.js";
17
+ export * from "./crawler.js";
18
+ export * from "./logUtils.js";
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,CAAC,OAAO,UAAU,OAAO;IAC7B,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,OAAO;QACd,WAAW;YACT,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE;gBACpB,YAAY,CAAC,GAAG,EAAE;oBAChB,WAAW,EAAE,CAAC;gBAChB,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AAED,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC"}
@@ -0,0 +1,24 @@
1
+ export class LogUtils {
2
+ static info(message) {
3
+ console.info(`\x1b[36m${message}\x1b[0m`);
4
+ }
5
+ static warn(message) {
6
+ console.warn(`\x1b[33m${message}\x1b[0m`);
7
+ }
8
+ static error(message) {
9
+ console.error(`\x1b[31m${message}\x1b[0m`);
10
+ }
11
+ static success(message) {
12
+ console.log(`\x1b[32m${message}\x1b[0m`);
13
+ }
14
+ static log(message) {
15
+ console.log(message);
16
+ }
17
+ static startPrintingGray() {
18
+ return '\x1b[90m';
19
+ }
20
+ static endPrintingGray() {
21
+ return '\x1b[0m';
22
+ }
23
+ }
24
+ //# sourceMappingURL=logUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logUtils.js","sourceRoot":"","sources":["../src/logUtils.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAQ;IACnB,MAAM,CAAC,IAAI,CAAC,OAAe;QACzB,OAAO,CAAC,IAAI,CAAC,WAAW,OAAO,SAAS,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,OAAe;QACzB,OAAO,CAAC,IAAI,CAAC,WAAW,OAAO,SAAS,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,OAAe;QAC1B,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,SAAS,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,CAAC,OAAO,CAAC,OAAe;QAC5B,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,SAAS,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,OAAe;QACxB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,CAAC,iBAAiB;QACtB,OAAO,UAAU,CAAA;IACnB,CAAC;IACD,MAAM,CAAC,eAAe;QACpB,OAAO,SAAS,CAAA;IAClB,CAAC;CACF"}
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "rendela",
3
+ "version": "1.1.8",
4
+ "description": "A tool for pre-rendering pages of your SPA to improve SEO and performance",
5
+ "author": "llopary",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "bin": {
11
+ "rendela": "./dist/cli.js"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/index.js",
19
+ "types": "./dist/types/index.d.ts"
20
+ },
21
+ "./config": {
22
+ "import": "./dist/config.js",
23
+ "types": "./dist/types/config.d.ts"
24
+ },
25
+ "./server": {
26
+ "import": "./dist/server.js",
27
+ "types": "./dist/types/server.d.ts"
28
+ },
29
+ "./crawler": {
30
+ "import": "./dist/crawler.js",
31
+ "types": "./dist/types/crawler.d.ts"
32
+ },
33
+ "./logUtils": {
34
+ "import": "./dist/utils/logUtils.js",
35
+ "types": "./dist/types/utils/logUtils.d.ts"
36
+ },
37
+ "./cli": {
38
+ "import": "./dist/cli.js",
39
+ "types": "./dist/types/cli.d.ts"
40
+ }
41
+ },
42
+ "scripts": {
43
+ "build": "tsc",
44
+ "dev": "tsc --watch",
45
+ "prepare": "tsc",
46
+ "pub": "npm run build && npm publish --no-git-checks"
47
+ },
48
+ "devDependencies": {
49
+ "typescript": "^5.8.2",
50
+ "vite": "^5.0.0"
51
+ },
52
+ "dependencies": {
53
+ "playwright": "^1.52.0",
54
+ "puppeteer": "^24.5.0"
55
+ }
56
+ }
@@ -0,0 +1,115 @@
1
+ # Rendela - SPA Page Prerendering Plugin
2
+
3
+ `Rendela` is a powerful tool designed to optimize Single Page Applications (SPAs) by prerendering them for better SEO, performance, and overall user experience. It helps search engines to index your pages more effectively, improves load times, and enhances the visibility of your site.
4
+
5
+ ## Key Features
6
+ - **SEO Optimization:** Prerenders pages to ensure they are properly indexed by search engines.
7
+ - **Faster Load Times:** By prerendering pages, users get content faster on their first visit.
8
+ - **Easy Integration:** Easily integrates with your existing SPA built with frameworks like Vue, React, etc.
9
+ - **Works with Vite:** This package works seamlessly with Vite to optimize SPA performance.
10
+
11
+ ## Prerequisites
12
+
13
+ Before you start using `rendela`, you will need to install **Chromium** on your machine. This is required to properly prerender the pages as `rendela` uses Chromium in headless mode for rendering.
14
+
15
+ ### Installation for Chromium
16
+
17
+ #### On Ubuntu/Debian (Linux)
18
+
19
+ 1. First, update your package list:
20
+ ```bash
21
+ sudo apt update
22
+ ```
23
+
24
+ 2. Then, install Chromium:
25
+ ```bash
26
+ sudo apt install chromium
27
+ ```
28
+
29
+ 3. Verify the installation by running:
30
+ ```bash
31
+ chromium --version
32
+ ```
33
+
34
+ This should show the installed Chromium version.
35
+
36
+ #### On Windows
37
+
38
+ 1. **Download Chromium**: You can download the latest stable version of Chromium from the [official website](https://download-chromium.appspot.com/).
39
+
40
+ 2. **Extract the Archive**: Extract the downloaded `.zip` file to a location of your choice (e.g., `C:\Program Files\Chromium`).
41
+
42
+ 3. **Set the Path**: You need to add the path to the Chromium executable in your system’s PATH environment variable.
43
+ - Open **System Properties** > **Environment Variables**.
44
+ - Under **System Variables**, find and select `Path`, then click **Edit**.
45
+ - Click **New**, and add the path to the folder where Chromium is located (e.g., `C:\Program Files\Chromium`).
46
+
47
+ 4. Verify the installation by running the following command in a terminal or command prompt:
48
+ ```bash
49
+ chromium --version
50
+ ```
51
+
52
+ #### On macOS
53
+
54
+ 1. **Install Chromium**: You can install Chromium using Homebrew. If you don't have Homebrew installed, first install it by running:
55
+ ```bash
56
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
57
+ ```
58
+
59
+ 2. **Install Chromium** via Homebrew:
60
+ ```bash
61
+ brew install chromium
62
+ ```
63
+
64
+ 3. Verify the installation by running:
65
+ ```bash
66
+ chromium --version
67
+ ```
68
+
69
+ If you don't use Homebrew, you can manually download Chromium from the [official website](https://download-chromium.appspot.com/) and follow similar steps as for Windows.
70
+
71
+ ---
72
+
73
+ ## Installation
74
+
75
+ Once Chromium is installed on your machine, you can proceed to install `rendela` as a Vite plugin.
76
+
77
+ 1. Install the package via npm or yarn:
78
+ ```bash
79
+ npm install @rendela/vite
80
+ # or
81
+ yarn add @rendela/vite
82
+ ```
83
+
84
+ 2. Add `rendela` to your `vite.config.js`:
85
+ ```javascript
86
+ import { defineConfig } from 'vite'
87
+ import rendela from '@rendela/vite'
88
+
89
+ export default defineConfig({
90
+ plugins: [rendela()],
91
+ })
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Usage
97
+
98
+ Once you've installed and configured `rendela` with Vite, it will automatically handle prerendering of your SPA pages when you build your project.
99
+
100
+ ### How It Works
101
+ - `rendela` will use the installed Chromium instance in headless mode to render and capture your pages.
102
+ - It generates static HTML files of your pages that can be served to crawlers or users, ensuring better SEO and performance.
103
+
104
+ ---
105
+
106
+ ## Additional Notes
107
+
108
+ - Make sure your Chromium installation is accessible from your system's PATH for `rendela` to function properly.
109
+ - If you're running the plugin in a CI environment, make sure the Chromium binary is installed and available.
110
+
111
+ ---
112
+
113
+ ## License
114
+
115
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
package/dist/server.js ADDED
@@ -0,0 +1,122 @@
1
+ import path from "path";
2
+ import http from "http";
3
+ import fs from "fs";
4
+ import { startCrawler } from "./crawler.js";
5
+ import { LogUtils } from "./logUtils.js";
6
+ import { createDefaultConfigFile, getConfig } from "./config.js";
7
+ const fileExtensionRegex = /\.[a-zA-Z0-9]+$/;
8
+ export async function startServer(isCli = false) {
9
+ const message = createDefaultConfigFile();
10
+ const startTime = Date.now();
11
+ const config = await getConfig();
12
+ if (!isCli && !config.autoStartOnBuild) {
13
+ return;
14
+ }
15
+ if (config.debug) {
16
+ LogUtils.info("");
17
+ LogUtils.info("");
18
+ LogUtils.info("------------------------------------");
19
+ LogUtils.info(" Welcome to Rendela ");
20
+ LogUtils.info("------------------------------------");
21
+ if (message) {
22
+ LogUtils.error(message);
23
+ LogUtils.info("");
24
+ }
25
+ LogUtils.warn("Starting pre-rendering the pages...");
26
+ }
27
+ const server = http.createServer((req, res) => {
28
+ if (!req.url) {
29
+ return return404(res);
30
+ }
31
+ const isAsset = req.url.startsWith("/assets") || fileExtensionRegex.test(req.url);
32
+ const distDir = path.resolve(process.cwd(), config.buildDir);
33
+ const filePath = path.join(distDir, isAsset ? req.url : "index.html");
34
+ const exists = fs.existsSync(filePath);
35
+ if (!exists) {
36
+ return return404(res);
37
+ }
38
+ fs.readFile(filePath, (err, data) => {
39
+ if (err) {
40
+ res.writeHead(500, { "Content-Type": "text/plain" });
41
+ res.end("500 Internal Server Error");
42
+ return;
43
+ }
44
+ const extname = path.extname(filePath);
45
+ let contentType = contentTypeMap[extname] || "text/html";
46
+ res.writeHead(200, { "Content-Type": contentType });
47
+ res.end(data);
48
+ });
49
+ });
50
+ const port = config.port ?? 3000;
51
+ server.listen(port, () => {
52
+ if (config.debug) {
53
+ LogUtils.warn(`The server to crawl the pages is running at http://localhost:${port}`);
54
+ LogUtils.info("");
55
+ }
56
+ setTimeout(async () => {
57
+ await startCrawler(config);
58
+ server.close();
59
+ const endTime = Date.now();
60
+ const duration = endTime - startTime;
61
+ LogUtils.success(`✓ Pre-rendered in ${(duration / 1000).toFixed(2)}s`);
62
+ }, 1000);
63
+ });
64
+ }
65
+ function return404(res) {
66
+ res.writeHead(404, { "Content-Type": "text/plain" });
67
+ res.end("404 Not Found");
68
+ }
69
+ const contentTypeMap = {
70
+ ".js": "application/javascript",
71
+ ".mjs": "application/javascript",
72
+ ".cjs": "application/javascript",
73
+ ".ts": "application/typescript",
74
+ ".tsx": "application/typescript",
75
+ ".css": "text/css",
76
+ ".json": "application/json",
77
+ ".csv": "text/csv",
78
+ ".txt": "text/plain",
79
+ ".html": "text/html",
80
+ ".htm": "text/html",
81
+ ".xhtml": "application/xhtml+xml",
82
+ ".md": "text/markdown",
83
+ ".yaml": "application/x-yaml",
84
+ ".yml": "application/x-yaml",
85
+ ".png": "image/png",
86
+ ".jpg": "image/jpeg",
87
+ ".jpeg": "image/jpeg",
88
+ ".gif": "image/gif",
89
+ ".svg": "image/svg+xml",
90
+ ".ico": "image/x-icon",
91
+ ".bmp": "image/bmp",
92
+ ".tiff": "image/tiff",
93
+ ".tif": "image/tiff",
94
+ ".webp": "image/webp",
95
+ ".pdf": "application/pdf",
96
+ ".xml": "application/xml",
97
+ ".zip": "application/zip",
98
+ ".tar": "application/x-tar",
99
+ ".rar": "application/vnd.rar",
100
+ ".7z": "application/x-7z-compressed",
101
+ ".mp4": "video/mp4",
102
+ ".m4v": "video/x-m4v",
103
+ ".webm": "video/webm",
104
+ ".mov": "video/quicktime",
105
+ ".avi": "video/x-msvideo",
106
+ ".wmv": "video/x-ms-wmv",
107
+ ".flv": "video/x-flv",
108
+ ".mp3": "audio/mpeg",
109
+ ".wav": "audio/wav",
110
+ ".ogg": "audio/ogg",
111
+ ".flac": "audio/flac",
112
+ ".aac": "audio/aac",
113
+ ".midi": "audio/midi",
114
+ ".mid": "audio/midi",
115
+ ".opus": "audio/opus",
116
+ ".woff": "font/woff",
117
+ ".woff2": "font/woff2",
118
+ ".ttf": "font/ttf",
119
+ ".eot": "application/vnd.ms-fontobject",
120
+ ".otf": "font/otf",
121
+ };
122
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,22 @@
1
+ export declare const rootPath: string;
2
+ export declare const configFilePath: string;
3
+ export declare const defaultConfig = "// @ts-check\n/**\n * @type {import('rendela').RendelaConfigType}\n */\nexport default {\n pages: [{ url: \"/\" }, { url: \"/signin\" }, { url: \"/signup\" }], // list of pages to render ({url: string, filename?: string, timeout?: number})\n buildDir: \"dist\", // application build directory\n port: 3300, // port to run the server on when rendering\n savePath: \"pages\", // path to save the rendered pages\n pageWaitTime: 10, // timeout for the page to load in ms\n pageTimeout: 5000, // timeout for the page to load in ms\n debug: true, // enable debug mode\n autoStartOnBuild: true, // auto start the server on build\n concurrencyLimit: 3, // number of concurrent pages to render\n};\n";
4
+ export declare function createDefaultConfigFile(): "Config file not found, creating default config" | null;
5
+ export declare function getConfig(): Promise<RendelaConfigType>;
6
+ export interface RendelaConfigType {
7
+ pages: RendelaPageType[];
8
+ buildDir: string;
9
+ port?: number;
10
+ savePath?: string;
11
+ pageWaitTime?: number;
12
+ pageTimeout?: number;
13
+ debug?: boolean;
14
+ autoStartOnBuild?: boolean;
15
+ chromiumExecutablePath?: string;
16
+ concurrencyLimit?: number;
17
+ }
18
+ export interface RendelaPageType {
19
+ url: string;
20
+ filename?: string;
21
+ timeout?: number;
22
+ }
@@ -0,0 +1,2 @@
1
+ import { RendelaConfigType } from './config.js';
2
+ export declare function startCrawler(config: RendelaConfigType): Promise<void>;
@@ -0,0 +1,6 @@
1
+ import { Plugin } from "vite";
2
+ export default function rendela(): Plugin;
3
+ export * from "./server.js";
4
+ export * from "./config.js";
5
+ export * from "./crawler.js";
6
+ export * from "./logUtils.js";
@@ -0,0 +1,9 @@
1
+ export declare class LogUtils {
2
+ static info(message: string): void;
3
+ static warn(message: string): void;
4
+ static error(message: string): void;
5
+ static success(message: string): void;
6
+ static log(message: string): void;
7
+ static startPrintingGray(): string;
8
+ static endPrintingGray(): string;
9
+ }
@@ -0,0 +1 @@
1
+ export declare function startServer(isCli?: boolean): Promise<void>;
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@rendela/vite",
3
+ "version": "0.0.1",
4
+ "description": "A tool for pre-rendering pages of your SPA to improve SEO and performance",
5
+ "author": "llopary",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "bin": {
11
+ "rendela": "dist/cli.js"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/index.js",
19
+ "types": "./dist/index.d.ts"
20
+ },
21
+ "./config": {
22
+ "import": "./dist/config.js",
23
+ "types": "./dist/types/config.d.ts"
24
+ },
25
+ "./server": {
26
+ "import": "./dist/server.js",
27
+ "types": "./dist/types/server.d.ts"
28
+ },
29
+ "./crawler": {
30
+ "import": "./dist/crawler.js",
31
+ "types": "./dist/types/crawler.d.ts"
32
+ },
33
+ "./logUtils": {
34
+ "import": "./dist/utils/logUtils.js",
35
+ "types": "./dist/types/utils/logUtils.d.ts"
36
+ },
37
+ "./cli": {
38
+ "import": "./dist/cli.js",
39
+ "types": "./dist/types/cli.d.ts"
40
+ }
41
+ },
42
+ "scripts": {
43
+ "build": "tsc",
44
+ "dev": "tsc --watch",
45
+ "prepare": "tsc",
46
+ "pub": "npm run build && cp README.md dist/README.md && npm publish --no-git-checks --access=public",
47
+ "postinstall": "npx playwright install"
48
+ },
49
+ "devDependencies": {
50
+ "typescript": "^5.8.2",
51
+ "vite": "^5.0.0"
52
+ },
53
+ "dependencies": {
54
+ "playwright": "^1.52.0"
55
+ },
56
+ "keywords": [
57
+ "vite",
58
+ "plugin",
59
+ "pre-render",
60
+ "playwright",
61
+ "seo",
62
+ "spa"
63
+ ],
64
+ "engines": {
65
+ "node": ">=18"
66
+ },
67
+ "publishConfig": {
68
+ "access": "public"
69
+ }
70
+ }