Skip to content

Commit aad7fa2

Browse files
split implementation by compiler
1 parent 353dff3 commit aad7fa2

File tree

10 files changed

+2524
-257
lines changed

10 files changed

+2524
-257
lines changed

packages/ssr/README.md

+34-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> A package for server-side rendering Stencil components.
44
5-
This package provides utilities for server-side rendering Stencil components in React. You can use it in Next.js or Vite based applications, e.g. Remix.
5+
This package provides utilities for server-side rendering Stencil components in React. You can use it in Webpack, Next.js or Vite based applications, e.g. Remix.
66

77
## Install
88

@@ -14,6 +14,10 @@ $ npm install --save-dev @stencil/ssr
1414

1515
## Setup
1616

17+
The package exports plugins for different compiler.
18+
19+
### Vite
20+
1721
In your e.g. Vite configuration, add the `stencilSSR` plugin as following:
1822

1923
```ts
@@ -55,6 +59,29 @@ export default stencilSSR({
5559
})(nextConfig);
5660
```
5761

62+
### Webpack
63+
64+
In Webpack configurations you can set up this plugin as following:
65+
66+
```ts
67+
const { StencilSSRWebpackPlugin } = require('@stencil/ssr/webpack')
68+
69+
module.exports = {
70+
//...
71+
plugins: [
72+
new StencilSSRWebpackPlugin({
73+
module: import('component-library-react'),
74+
from: 'component-library-react',
75+
hydrateModule: import('component-library/hydrate'),
76+
serializeShadowRoot: {
77+
'scoped': ['my-counter'],
78+
default: 'declarative-shadow-dom',
79+
},
80+
})
81+
],
82+
};
83+
```
84+
5885
## Options
5986

6087
The plugin requires the following options:
@@ -70,3 +97,9 @@ The name of the library that exposes your Stencil components.
7097
### `hydrateModule`
7198

7299
The import of the hydrate module generated by the [Stencil hydrate output target](https://stenciljs.com/docs/hydrate-app#how-to-use-the-hydrate-app).
100+
101+
For more information about Server Side Rendering with Stencil, checkout the [documentation](https://stenciljs.com/docs/server-side-rendering).
102+
103+
### `runtime`
104+
105+
The reference to the runtime package.

packages/ssr/package.json

+24-11
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,30 @@
1212
"bugs": {
1313
"url": "https://github.com/stenciljs/output-targets/issues"
1414
},
15-
"main": "./dist/index.js",
16-
"module": "./dist/index.js",
17-
"types": "./dist/index.d.ts",
15+
"main": "./dist/vite.cjs",
16+
"module": "./dist/vite.js",
17+
"types": "./dist/vite/index.d.ts",
1818
"type": "module",
1919
"exports": {
2020
".": {
21-
"types": "./dist/index.d.ts",
22-
"import": "./dist/index.js"
21+
"types": "./dist/vite/index.d.ts",
22+
"import": "./dist/vite.js",
23+
"require": "./dist/vite.cjs"
24+
},
25+
"./vite": {
26+
"types": "./dist/vite/index.d.ts",
27+
"import": "./dist/vite.js",
28+
"require": "./dist/vite.cjs"
2329
},
2430
"./next": {
25-
"types": "./dist/next.d.ts",
26-
"import": "./dist/next.js"
31+
"types": "./dist/next/index.d.ts",
32+
"import": "./dist/next.js",
33+
"require": "./dist/next.cjs"
34+
},
35+
"./webpack": {
36+
"types": "./dist/webpack/index.d.ts",
37+
"import": "./dist/webpack.js",
38+
"require": "./dist/webpack.cjs"
2739
}
2840
},
2941
"files": [
@@ -34,8 +46,8 @@
3446
},
3547
"scripts": {
3648
"prepublishOnly": "pnpm run build",
37-
"build": "tsc -p tsconfig.json",
38-
"dev": "tsc -p tsconfig.json --watch",
49+
"build": "vite build",
50+
"dev": "vite build --watch",
3951
"version": "pnpm run build",
4052
"prettier": "prettier \"./src/**/*.{html,ts,tsx,js,jsx}\" --write",
4153
"release": "np",
@@ -48,7 +60,7 @@
4860
"component-library": "workspace:*",
4961
"component-library-react": "workspace:*",
5062
"typescript": "^5.4.4",
51-
"webpack": "^5.98.0"
63+
"vite-plugin-dts": "^4.5.3"
5264
},
5365
"dependencies": {
5466
"ast-types": "^0.14.2",
@@ -60,6 +72,7 @@
6072
},
6173
"peerDependencies": {
6274
"vite": "^6.x",
63-
"next": "13 || 14 || 15"
75+
"next": "13 || 14 || 15",
76+
"webpack": "^5.x"
6477
}
6578
}

packages/ssr/src/next.ts

-53
This file was deleted.

packages/ssr/src/next/index.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import type { Configuration } from 'webpack';
2+
import type { NextConfig } from 'next';
3+
import type { NextJsWebpackConfig, WebpackConfigContext } from 'next/dist/server/config-shared';
4+
5+
import { StencilSSRWebpackPlugin, MinimalWebpackConfig } from '../webpack/index.js';
6+
import type { StencilSSROptions } from '../types.js';
7+
8+
type StencilNextPlugin = (nextConfig: any) => NextConfig;
9+
10+
export default (pluginOptions: StencilSSROptions): StencilNextPlugin => (nextConfig: NextConfig = {}) => {
11+
const stencilSSRWebpackPlugin = new StencilSSRWebpackPlugin({
12+
...pluginOptions,
13+
include: /\/pages\/.*\.(?:j|t)sx?$|\/app\/.*\.(?:j|t)sx?$/,
14+
exclude: [/next\/dist\//, /node_modules/]
15+
});
16+
17+
const webpack: NextJsWebpackConfig = (config: Configuration, options: WebpackConfigContext) => {
18+
if (!config.module) {
19+
config.module = {}
20+
}
21+
22+
if (!config.module.rules) {
23+
config.module.rules = []
24+
}
25+
26+
stencilSSRWebpackPlugin.apply({ options: config as MinimalWebpackConfig['options'] });
27+
28+
// Apply user provided custom webpack config function if it exists.
29+
if (typeof nextConfig.webpack === 'function') {
30+
return nextConfig.webpack(config, options);
31+
}
32+
33+
return config;
34+
};
35+
36+
return Object.assign({}, nextConfig, { webpack });
37+
};
38+
39+
export * from '../types.js';

packages/ssr/src/index.ts packages/ssr/src/vite/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Plugin } from 'vite';
22

3-
import { transform } from './transform.js';
4-
import type { StencilSSROptions } from './types.js';
3+
import { transform } from '../transform.js';
4+
import type { StencilSSROptions } from '../types.js';
55

66
export function stencilSSR(pluginOptions: StencilSSROptions) {
77
return {

packages/ssr/src/webpack/index.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import path from 'node:path';
2+
import url from 'node:url';
3+
4+
import type { RuleSetRule } from 'webpack';
5+
6+
import type { StencilSSROptions } from '../types.js';
7+
8+
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
9+
10+
export interface StencilSSRWebpackPluginOptions extends StencilSSROptions {
11+
/**
12+
* A regex matching the files that may include Stencil components
13+
*/
14+
include?: RegExp;
15+
/**
16+
* A regex matching the files that should be ignored by the plugin
17+
*/
18+
exclude?: RegExp[];
19+
/**
20+
* The package reference that contains the Stencil runtime, e.g. `component-library/loader`
21+
*/
22+
runtime?: string;
23+
}
24+
25+
export interface MinimalWebpackConfig {
26+
options: {
27+
module: {
28+
rules: RuleSetRule[];
29+
};
30+
};
31+
}
32+
33+
/**
34+
* A simple Webpack plugin that adds a banner comment to the top of output files.
35+
*/
36+
export class StencilSSRWebpackPlugin {
37+
#options: StencilSSROptions;
38+
#include: RegExp;
39+
#exclude: RegExp[];
40+
constructor(options: StencilSSRWebpackPluginOptions) {
41+
this.#options = options;
42+
this.#include = options.include ?? /\.(jsx|tsx)$/;
43+
this.#exclude = options.exclude ?? [/node_modules/];
44+
}
45+
46+
apply(compiler: MinimalWebpackConfig): void {
47+
/**
48+
* adds our loader to the webpack config
49+
*/
50+
compiler.options.module.rules.push({
51+
test: this.#include,
52+
exclude: this.#exclude,
53+
enforce: 'pre',
54+
use: [
55+
{
56+
loader: path.resolve(__dirname, 'loader.js'),
57+
options: this.#options,
58+
},
59+
],
60+
});
61+
}
62+
}
File renamed without changes.

packages/ssr/test/next/loader.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, it, expect, vi, beforeEach } from 'vitest';
2-
import stencilLoader from '../../src/next/loader.js';
2+
import stencilLoader from '../../src/webpack/loader.js';
33
import { transform } from '../../src/transform.js';
44

55
// Mock the transform module

packages/ssr/vite.config.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
// vite.config.ts
22
import { defineConfig } from 'vite';
3-
3+
import dts from 'vite-plugin-dts';
44
export default defineConfig({
55
build: {
66
lib: {
77
entry: {
8-
index: 'src/index.ts',
9-
next: 'src/next.ts'
8+
vite: 'src/vite/index.ts',
9+
next: 'src/next/index.ts',
10+
webpack: 'src/webpack/index.ts',
11+
loader: 'src/webpack/loader.ts',
1012
},
1113
formats: ['es', 'cjs'],
1214
},
1315
rollupOptions: {
1416
// make sure to externalize deps that shouldn't be bundled
1517
// into your library
1618
external: [
17-
'node:path', 'node:url', 'node:fs',
19+
'node:path', 'node:url', 'node:fs', 'webpack', 'next', 'vite',
1820
'@stencil/core', '@lit/react', 'typescript', 'react', 'react-dom/server', 'ts-morph',
1921
'html-react-parser', 'mlly', 'esbuild', 'recast', 'ast-types',
2022
]
2123
},
2224
},
25+
plugins: [dts()]
2326
});

0 commit comments

Comments
 (0)