@vyriy/webpack-config 0.4.7 → 0.4.8

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
@@ -8,6 +8,7 @@ This package provides small typed Webpack helpers for Vyriy client and server bu
8
8
 
9
9
  - browser and SSR config generators
10
10
  - an HTML plugin helper backed by `html-webpack-plugin` and `@vyriy/html`
11
+ - reusable script and style module rules
11
12
  - a node_modules externalizer for server bundles
12
13
 
13
14
  ## Install
@@ -158,4 +159,33 @@ HTML plugin defaults:
158
159
  - minification enabled for whitespace, comments, JS, and CSS
159
160
  - local plugin options override shared defaults
160
161
 
162
+ ## Style Rules
163
+
164
+ The `style(options?)` helper creates the shared CSS/SCSS/Sass rule:
165
+
166
+ ```ts
167
+ import { style } from '@vyriy/webpack-config';
168
+
169
+ style({ mode: 'inject' });
170
+ style({ mode: 'extract' });
171
+ style({ mode: 'ignore' });
172
+ ```
173
+
174
+ Modes:
175
+
176
+ - `inject` uses `style-loader`, so ordinary style imports are inserted into the document head.
177
+ - `extract` uses `mini-css-extract-plugin`, so ordinary style imports become CSS files that can be linked by HTML or served by webpack-dev-server.
178
+ - `ignore` uses `null-loader`, which is useful for SSR bundles.
179
+
180
+ All non-ignored modes also support inline CSS string imports:
181
+
182
+ ```ts
183
+ import css from './profile-card.scss?inline';
184
+
185
+ const styles = document.createElement('style');
186
+ styles.textContent = css;
187
+ ```
188
+
189
+ This is useful for custom elements that place styles inside a Shadow DOM. When a custom element should use a linked stylesheet instead, use `style({ mode: 'extract' })` and add `MiniCssExtractPlugin` to the Webpack plugins in both production and development. Webpack dev server can serve the extracted CSS from memory, while production emits the same kind of CSS asset to disk.
190
+
161
191
  See the article with a complete browser and SSR bundling walkthrough: <https://vyriy.dev/examples/vyriy-webpack-config/>.
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './csr.js';
2
2
  export * from './external.js';
3
3
  export * from './html.js';
4
+ export * from './rules.js';
4
5
  export * from './ssr.js';
5
6
  export type * from './types.js';
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './csr.js';
2
2
  export * from './external.js';
3
3
  export * from './html.js';
4
+ export * from './rules.js';
4
5
  export * from './ssr.js';
package/package.json CHANGED
@@ -1,47 +1,8 @@
1
1
  {
2
2
  "name": "@vyriy/webpack-config",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
4
4
  "description": "Shared Webpack config for Vyriy projects",
5
5
  "type": "module",
6
- "dependencies": {
7
- "@babel/core": "^7.29.7",
8
- "@babel/plugin-transform-runtime": "^7.29.7",
9
- "@babel/preset-env": "^7.29.7",
10
- "@babel/preset-react": "^7.29.7",
11
- "@babel/preset-typescript": "^7.29.7",
12
- "@babel/register": "^7.29.7",
13
- "@babel/runtime": "^7.29.7",
14
- "@pmmmwh/react-refresh-webpack-plugin": "^0.6.2",
15
- "@vyriy/env": "0.4.7",
16
- "@vyriy/html": "0.4.7",
17
- "@vyriy/path": "0.4.7",
18
- "babel-loader": "^10.1.1",
19
- "css-loader": "^7.1.4",
20
- "cssnano": "^8.0.1",
21
- "html-webpack-plugin": "^5.6.7",
22
- "mini-css-extract-plugin": "^2.10.2",
23
- "null-loader": "^4.0.1",
24
- "postcss": "^8.5.15",
25
- "postcss-loader": "^8.2.1",
26
- "postcss-preset-env": "^11.3.0",
27
- "react-refresh": "^0.18.0",
28
- "sass": "^1.100.0",
29
- "sass-loader": "^17.0.0",
30
- "style-loader": "^4.0.0",
31
- "terser-webpack-plugin": "^5.6.0",
32
- "webpack": "^5.107.2",
33
- "webpack-cli": "^7.0.2",
34
- "webpack-dev-server": "^5.2.4"
35
- },
36
- "agents": "./AGENTS.md",
37
- "license": "MIT",
38
- "repository": {
39
- "type": "git",
40
- "url": "https://github.com/evheniy/vyriy",
41
- "directory": "packages/webpack"
42
- },
43
- "main": "./index.js",
44
- "types": "./index.d.ts",
45
6
  "exports": {
46
7
  ".": {
47
8
  "types": "./index.d.ts",
@@ -178,5 +139,44 @@
178
139
  "import": "./ssr.js",
179
140
  "default": "./ssr.js"
180
141
  }
181
- }
142
+ },
143
+ "dependencies": {
144
+ "@babel/core": "^7.29.7",
145
+ "@babel/plugin-transform-runtime": "^7.29.7",
146
+ "@babel/preset-env": "^7.29.7",
147
+ "@babel/preset-react": "^7.29.7",
148
+ "@babel/preset-typescript": "^7.29.7",
149
+ "@babel/register": "^7.29.7",
150
+ "@babel/runtime": "^7.29.7",
151
+ "@pmmmwh/react-refresh-webpack-plugin": "^0.6.2",
152
+ "@vyriy/env": "0.4.8",
153
+ "@vyriy/html": "0.4.8",
154
+ "@vyriy/path": "0.4.8",
155
+ "babel-loader": "^10.1.1",
156
+ "css-loader": "^7.1.4",
157
+ "cssnano": "^8.0.1",
158
+ "html-webpack-plugin": "^5.6.7",
159
+ "mini-css-extract-plugin": "^2.10.2",
160
+ "null-loader": "^4.0.1",
161
+ "postcss": "^8.5.15",
162
+ "postcss-loader": "^8.2.1",
163
+ "postcss-preset-env": "^11.3.0",
164
+ "react-refresh": "^0.18.0",
165
+ "sass": "^1.100.0",
166
+ "sass-loader": "^17.0.0",
167
+ "style-loader": "^4.0.0",
168
+ "terser-webpack-plugin": "^5.6.1",
169
+ "webpack": "^5.107.2",
170
+ "webpack-cli": "^7.0.3",
171
+ "webpack-dev-server": "^5.2.4"
172
+ },
173
+ "agents": "./AGENTS.md",
174
+ "license": "MIT",
175
+ "repository": {
176
+ "type": "git",
177
+ "url": "https://github.com/evheniy/vyriy",
178
+ "directory": "packages/webpack"
179
+ },
180
+ "main": "./index.js",
181
+ "types": "./index.d.ts"
182
182
  }
package/rules.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { RuleSetRule } from 'webpack';
2
+ import type { WebpackStyleRuleOptions } from './types.js';
2
3
  export declare const SCRIPT_TEST: RegExp;
3
4
  export declare const STYLE_TEST: RegExp;
5
+ export declare const style: ({ mode }?: WebpackStyleRuleOptions) => RuleSetRule;
4
6
  export declare const rules: (isSsr?: boolean, isProduction?: boolean) => RuleSetRule[];
package/rules.js CHANGED
@@ -4,29 +4,71 @@ import { postcss } from './postcss.js';
4
4
  import { resolveDependency } from './resolve-dependency.js';
5
5
  export const SCRIPT_TEST = /\.(mjs|cjs|js|jsx|mts|cts|ts|tsx)$/;
6
6
  export const STYLE_TEST = /\.(css|scss|sass)$/;
7
- export const rules = (isSsr = false, isProduction = true) => [
8
- {
9
- test: SCRIPT_TEST,
10
- exclude: /node_modules/,
11
- use: {
12
- loader: resolveDependency('babel-loader'),
13
- options: babel(isSsr, isProduction),
14
- },
7
+ const postcssLoader = () => ({
8
+ loader: resolveDependency('postcss-loader'),
9
+ options: {
10
+ postcssOptions: postcss(),
15
11
  },
12
+ });
13
+ const styleLoader = (mode) => {
14
+ return mode === 'extract' ? MiniCssExtractPlugin.loader : resolveDependency('style-loader');
15
+ };
16
+ const stylesheetLoaders = (mode) => [
17
+ styleLoader(mode),
18
+ resolveDependency('css-loader'),
19
+ postcssLoader(),
20
+ resolveDependency('sass-loader'),
21
+ ];
22
+ const inlineStylesheetLoaders = () => [
16
23
  {
17
- test: STYLE_TEST,
18
- use: isSsr
19
- ? [resolveDependency('null-loader')]
20
- : [
21
- isProduction ? MiniCssExtractPlugin.loader : resolveDependency('style-loader'),
22
- resolveDependency('css-loader'),
23
- {
24
- loader: resolveDependency('postcss-loader'),
25
- options: {
26
- postcssOptions: postcss(),
27
- },
28
- },
29
- resolveDependency('sass-loader'),
30
- ],
24
+ loader: resolveDependency('css-loader'),
25
+ options: {
26
+ exportType: 'string',
27
+ },
31
28
  },
29
+ postcssLoader(),
30
+ resolveDependency('sass-loader'),
32
31
  ];
32
+ export const style = ({ mode = 'extract' } = {}) => {
33
+ if (mode === 'ignore') {
34
+ return {
35
+ test: STYLE_TEST,
36
+ use: [resolveDependency('null-loader')],
37
+ };
38
+ }
39
+ return {
40
+ test: STYLE_TEST,
41
+ oneOf: [
42
+ {
43
+ resourceQuery: /inline/,
44
+ use: inlineStylesheetLoaders(),
45
+ },
46
+ {
47
+ use: stylesheetLoaders(mode),
48
+ },
49
+ ],
50
+ };
51
+ };
52
+ export const rules = (isSsr = false, isProduction = true) => {
53
+ let mode;
54
+ if (isSsr) {
55
+ mode = 'ignore';
56
+ }
57
+ else if (isProduction) {
58
+ mode = 'extract';
59
+ }
60
+ else {
61
+ mode = 'inject';
62
+ }
63
+ return [
64
+ {
65
+ test: SCRIPT_TEST,
66
+ exclude: /node_modules/,
67
+ use: {
68
+ loader: resolveDependency('babel-loader'),
69
+ options: babel(isSsr, isProduction),
70
+ },
71
+ },
72
+ style({ mode }),
73
+ ];
74
+ };
package/types.d.ts CHANGED
@@ -7,3 +7,7 @@ export type WebpackExternal = Extract<NonNullable<Configuration['externals']>, u
7
7
  export type NodeModulesExternalOptions = {
8
8
  allowlist?: (RegExp | string)[];
9
9
  };
10
+ export type WebpackStyleMode = 'extract' | 'ignore' | 'inject';
11
+ export type WebpackStyleRuleOptions = {
12
+ mode?: WebpackStyleMode;
13
+ };