@vyriy/webpack-config 0.3.5 → 0.3.9

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 CHANGED
@@ -4,20 +4,24 @@ Shared Webpack config for Vyriy projects.
4
4
 
5
5
  ## Purpose
6
6
 
7
- This package provides two small typed Webpack config generators for Vyriy client and server builds.
7
+ This package provides small typed Webpack helpers for Vyriy client and server builds:
8
+
9
+ - browser and SSR config generators
10
+ - an HTML plugin helper backed by `html-webpack-plugin` and `@vyriy/html`
11
+ - a node_modules externalizer for server bundles
8
12
 
9
13
  ## Install
10
14
 
11
15
  With npm:
12
16
 
13
17
  ```bash
14
- npm install @vyriy/webpack-config webpack webpack-cli
18
+ npm install @vyriy/webpack-config webpack-cli
15
19
  ```
16
20
 
17
21
  With Yarn:
18
22
 
19
23
  ```bash
20
- yarn add @vyriy/webpack-config webpack webpack-cli
24
+ yarn add @vyriy/webpack-config webpack-cli
21
25
  ```
22
26
 
23
27
  The `webpack` package is listed in the install command because the shared config is consumed by Webpack at build time. Add `webpack-cli` only when the consumer project runs Webpack through CLI commands.
@@ -39,44 +43,36 @@ export default csr('./src/index.tsx', {
39
43
  For SSR bundles:
40
44
 
41
45
  ```js
42
- import { ssr } from '@vyriy/webpack-config';
43
-
44
- export default ssr(['@w/api'], {
45
- path: '/absolute/path/to/dist/api',
46
- filename: 'index.js',
47
- library: { type: 'commonjs2' },
48
- clean: true,
49
- });
50
- ```
51
-
52
- The second parameter is a regular Webpack `output` config passed as-is.
53
-
54
- Both generators accept a third parameter with a local Webpack config transform. The transform receives the shared config and returns the final config, so the consumer can choose where to extend defaults and where to replace them:
46
+ import { ssr, external } from '@vyriy/webpack-config';
55
47
 
56
- ```js
57
- import { csr } from '@vyriy/webpack-config';
58
-
59
- export default csr(
60
- './src/index.tsx',
48
+ export default ssr(
49
+ ['@w/api'],
61
50
  {
62
- path: '/absolute/path/to/dist/client',
51
+ path: '/absolute/path/to/dist/api',
63
52
  filename: 'index.js',
53
+ library: { type: 'commonjs2' },
64
54
  clean: true,
65
55
  },
66
56
  (config) => ({
67
57
  ...config,
68
- optimization: {
69
- ...config.optimization,
70
- splitChunks: true,
71
- },
58
+ externals: [
59
+ ...(Array.isArray(config.externals) ? config.externals : []),
60
+ external({
61
+ allowlist: [/^@p/, /^@w/, /^@vyriy/],
62
+ }),
63
+ ],
72
64
  }),
73
65
  );
74
66
  ```
75
67
 
76
- For example, append a local CSR plugin while keeping the shared CSR plugin:
68
+ The second parameter is a regular Webpack `output` config passed as-is.
69
+
70
+ Both generators accept a third parameter with a local Webpack config transform. The transform receives the shared config and returns the final config, so the consumer can choose where to extend defaults and where to replace them.
71
+
72
+ For example, add an HTML document to a client build:
77
73
 
78
74
  ```js
79
- import { csr } from '@vyriy/webpack-config';
75
+ import { csr, html } from '@vyriy/webpack-config';
80
76
 
81
77
  export default csr(
82
78
  './src/index.tsx',
@@ -89,12 +85,32 @@ export default csr(
89
85
  ...config,
90
86
  plugins: [
91
87
  ...(config.plugins ?? []),
92
- new LocalPlugin(),
88
+ html({
89
+ title: '<title>App</title>',
90
+ body: '<div id="root"></div>',
91
+ }),
93
92
  ],
94
93
  }),
95
94
  );
96
95
  ```
97
96
 
97
+ The `html` helper accepts `HtmlProps` from `@vyriy/html` as the first parameter and optional `html-webpack-plugin` options as the second parameter:
98
+
99
+ ```js
100
+ import { html } from '@vyriy/webpack-config';
101
+
102
+ html(
103
+ {
104
+ title: '<title>App</title>',
105
+ meta: '<meta name="viewport" content="width=device-width, initial-scale=1" />',
106
+ body: '<div id="root"></div>',
107
+ },
108
+ {
109
+ filename: 'index.html',
110
+ },
111
+ );
112
+ ```
113
+
98
114
  With types:
99
115
 
100
116
  ```ts
@@ -113,6 +129,8 @@ export default config;
113
129
 
114
130
  - `csr(entry, output, transform?)` creates a browser-oriented Webpack config.
115
131
  - `ssr(entry, output, transform?)` creates a node-oriented SSR Webpack config.
132
+ - `html(props, options?)` creates an `HtmlWebpackPlugin` instance from `@vyriy/html` document sections.
133
+ - `external(options?)` creates a Webpack `externals` function that leaves bare package imports as CommonJS runtime imports.
116
134
  - `WebpackConfig`, `WebpackConfigTransform`, `WebpackEntry`, and `WebpackOutput` expose the shared config helper types.
117
135
 
118
136
  Shared defaults:
@@ -123,4 +141,18 @@ Shared defaults:
123
141
  - production `optimization` with `TerserPlugin`
124
142
  - merged `resolve` defaults
125
143
 
144
+ CSR defaults:
145
+
146
+ - production builds extract CSS with `MiniCssExtractPlugin`
147
+ - development builds enable React refresh with `ReactRefreshWebpackPlugin`
148
+
149
+ HTML plugin defaults:
150
+
151
+ - `templateContent` rendered from `@vyriy/html`
152
+ - `publicPath: '/'`
153
+ - `hash: true`
154
+ - `inject: 'body'`
155
+ - minification enabled for whitespace, comments, JS, and CSS
156
+ - local plugin options override shared defaults
157
+
126
158
  See the article with a complete browser and SSR bundling walkthrough: <https://vyriy.dev/examples/vyriy-webpack-config/>.
package/csr.js CHANGED
@@ -1,6 +1,6 @@
1
- import { path } from '@vyriy/path';
2
1
  import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
3
2
  import MiniCssExtractPlugin from 'mini-css-extract-plugin';
3
+ import { path } from '@vyriy/path';
4
4
  import { mode } from './mode.js';
5
5
  import { optimization } from './optimization.js';
6
6
  import { performance } from './performance.js';
package/external.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { NodeModulesExternalOptions, WebpackExternal } from './types.js';
2
+ export declare const external: (options?: NodeModulesExternalOptions) => WebpackExternal;
package/external.js ADDED
@@ -0,0 +1,15 @@
1
+ import { isAbsolute } from 'node:path';
2
+ const isPackageRequest = (request) => !request.startsWith('.') && !isAbsolute(request);
3
+ const matchesPattern = (pattern, request) => typeof pattern === 'string' ? pattern === request : pattern.test(request);
4
+ export const external = (options = {}) => {
5
+ const allowlist = options.allowlist ?? [];
6
+ return ({ request }, callback) => {
7
+ const shouldBundle = !request || !isPackageRequest(request) || allowlist.some((pattern) => matchesPattern(pattern, request));
8
+ if (shouldBundle) {
9
+ callback();
10
+ }
11
+ else {
12
+ callback(null, `commonjs ${request}`);
13
+ }
14
+ };
15
+ };
package/html.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import HtmlWebpackPlugin, { type Options } from 'html-webpack-plugin';
2
+ import { type HtmlProps } from '@vyriy/html';
3
+ export declare const html: (props: HtmlProps, options?: Options) => HtmlWebpackPlugin;
package/html.js ADDED
@@ -0,0 +1,18 @@
1
+ import HtmlWebpackPlugin from 'html-webpack-plugin';
2
+ import { html as page } from '@vyriy/html';
3
+ export const html = (props, options = {}) => {
4
+ return new HtmlWebpackPlugin({
5
+ templateContent: page(props),
6
+ publicPath: '/',
7
+ hash: true,
8
+ inject: 'body',
9
+ minify: {
10
+ removeComments: true,
11
+ collapseWhitespace: true,
12
+ removeAttributeQuotes: false,
13
+ minifyJS: true,
14
+ minifyCSS: true,
15
+ },
16
+ ...options,
17
+ });
18
+ };
package/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export * from './csr.js';
2
+ export * from './external.js';
3
+ export * from './html.js';
2
4
  export * from './ssr.js';
3
5
  export type * from './types.js';
package/index.js CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from './csr.js';
2
+ export * from './external.js';
3
+ export * from './html.js';
2
4
  export * from './ssr.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vyriy/webpack-config",
3
- "version": "0.3.5",
3
+ "version": "0.3.9",
4
4
  "description": "Shared Webpack config for Vyriy projects",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -13,11 +13,13 @@
13
13
  "@babel/register": "^7.29.3",
14
14
  "@babel/runtime": "^7.29.2",
15
15
  "@pmmmwh/react-refresh-webpack-plugin": "^0.6.2",
16
- "@vyriy/env": "0.3.5",
17
- "@vyriy/path": "0.3.5",
16
+ "@vyriy/env": "0.3.9",
17
+ "@vyriy/html": "0.3.9",
18
+ "@vyriy/path": "0.3.9",
18
19
  "babel-loader": "^10.1.1",
19
20
  "css-loader": "^7.1.4",
20
21
  "cssnano": "^8.0.1",
22
+ "html-webpack-plugin": "^5.6.7",
21
23
  "mini-css-extract-plugin": "^2.10.2",
22
24
  "null-loader": "^4.0.1",
23
25
  "postcss": "^8.5.15",
@@ -25,10 +27,10 @@
25
27
  "postcss-preset-env": "^11.3.0",
26
28
  "react-refresh": "^0.18.0",
27
29
  "sass": "^1.99.0",
28
- "sass-loader": "^16.0.8",
30
+ "sass-loader": "^17.0.0",
29
31
  "style-loader": "^4.0.0",
30
32
  "terser-webpack-plugin": "^5.6.0",
31
- "webpack": "^5.106.2"
33
+ "webpack": "^5.107.0"
32
34
  },
33
35
  "agents": "./AGENTS.md",
34
36
  "license": "MIT",
@@ -64,6 +66,26 @@
64
66
  "import": "./csr.js",
65
67
  "default": "./csr.js"
66
68
  },
69
+ "./external": {
70
+ "types": "./external.d.ts",
71
+ "import": "./external.js",
72
+ "default": "./external.js"
73
+ },
74
+ "./external.js": {
75
+ "types": "./external.d.ts",
76
+ "import": "./external.js",
77
+ "default": "./external.js"
78
+ },
79
+ "./html": {
80
+ "types": "./html.d.ts",
81
+ "import": "./html.js",
82
+ "default": "./html.js"
83
+ },
84
+ "./html.js": {
85
+ "types": "./html.d.ts",
86
+ "import": "./html.js",
87
+ "default": "./html.js"
88
+ },
67
89
  "./index": {
68
90
  "types": "./index.d.ts",
69
91
  "import": "./index.js",
package/types.d.ts CHANGED
@@ -3,3 +3,7 @@ export type WebpackConfig = Configuration;
3
3
  export type WebpackEntry = WebpackConfig['entry'];
4
4
  export type WebpackOutput = WebpackConfig['output'];
5
5
  export type WebpackConfigTransform = (config: WebpackConfig) => WebpackConfig;
6
+ export type WebpackExternal = Extract<NonNullable<Configuration['externals']>, unknown[]>[number];
7
+ export type NodeModulesExternalOptions = {
8
+ allowlist?: (RegExp | string)[];
9
+ };