@vyriy/webpack-config 0.4.7 → 0.4.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
@@ -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
@@ -146,7 +147,7 @@ Shared defaults:
146
147
  CSR defaults:
147
148
 
148
149
  - loaders and Babel extensions are resolved from this package for workspace and package-manager isolation
149
- - production builds extract CSS with `MiniCssExtractPlugin`
150
+ - CSS is extracted with `MiniCssExtractPlugin` in production and development
150
151
  - development builds enable React refresh with `ReactRefreshWebpackPlugin`
151
152
 
152
153
  HTML plugin defaults:
@@ -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. CSR builds extract ordinary stylesheet imports by default, so custom elements can also use a linked stylesheet without local rule replacement. 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/csr.js CHANGED
@@ -17,11 +17,14 @@ export const csr = (entry, output, transform) => {
17
17
  entry,
18
18
  output,
19
19
  module: {
20
- rules: rules(false, isProduction),
20
+ rules: rules(false, isProduction, 'extract'),
21
21
  },
22
22
  optimization: optimization(isProduction),
23
23
  performance,
24
- plugins: isProduction ? [new MiniCssExtractPlugin()] : [new ReactRefreshWebpackPlugin()],
24
+ plugins: [
25
+ new MiniCssExtractPlugin(),
26
+ ...(isProduction ? [] : [new ReactRefreshWebpackPlugin()]),
27
+ ],
25
28
  resolve: resolve(),
26
29
  };
27
30
  return transform ? transform(base) : base;
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.9",
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.9",
153
+ "@vyriy/html": "0.4.9",
154
+ "@vyriy/path": "0.4.9",
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 { WebpackStyleMode, WebpackStyleRuleOptions } from './types.js';
2
3
  export declare const SCRIPT_TEST: RegExp;
3
4
  export declare const STYLE_TEST: RegExp;
4
- export declare const rules: (isSsr?: boolean, isProduction?: boolean) => RuleSetRule[];
5
+ export declare const style: ({ mode }?: WebpackStyleRuleOptions) => RuleSetRule;
6
+ export declare const rules: (isSsr?: boolean, isProduction?: boolean, styleMode?: WebpackStyleMode) => RuleSetRule[];
package/rules.js CHANGED
@@ -4,29 +4,74 @@ 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, styleMode) => {
53
+ let mode;
54
+ if (isSsr) {
55
+ mode = 'ignore';
56
+ }
57
+ else if (styleMode) {
58
+ mode = styleMode;
59
+ }
60
+ else if (isProduction) {
61
+ mode = 'extract';
62
+ }
63
+ else {
64
+ mode = 'inject';
65
+ }
66
+ return [
67
+ {
68
+ test: SCRIPT_TEST,
69
+ exclude: /node_modules/,
70
+ use: {
71
+ loader: resolveDependency('babel-loader'),
72
+ options: babel(isSsr, isProduction),
73
+ },
74
+ },
75
+ style({ mode }),
76
+ ];
77
+ };
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
+ };