@razerspine/webpack-core 1.8.0 → 1.9.0

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/CHANGELOG.md CHANGED
@@ -8,6 +8,30 @@ required to ensure correct behavior in both development and production modes.
8
8
 
9
9
  ---
10
10
 
11
+ ## [1.9.0] - 2026-03-13
12
+
13
+ ### Added
14
+ - **Smart Auto-Hosting Adapter**
15
+ - Integrated `detectHosting()` utility to automatically identify deployment platforms (**Vercel, Netlify, Cloudflare, GitHub Pages**).
16
+ - **Zero-Config Routing**: Automatically generates platform-specific configuration files (`_redirects`, `vercel.json`) based on `appType`.
17
+ - **Interactive Build Logs**: Added `infrastructureLogger` integration. The build now informs the developer about detected platforms (e.g., `📦 Netlify detected. Generating _redirects for SPA...`).
18
+ - **Enhanced SPA Fallback Strategy**
19
+ - Automated `404.html` generation for **GitHub Pages** and static hosts when in SPA mode.
20
+ - Ensures seamless client-side routing without manual file duplication.
21
+
22
+ ### Changed
23
+ - **Architectural Refactoring**
24
+ - Decoupled hosting logic into specialized utilities: `getRedirects`, `getVercelConfig`, and `detectHosting`.
25
+ - Improved `createProdConfig` maintainability by moving business logic out of the main configuration factory.
26
+ - **Production Alignment**
27
+ - `createProdConfig` now actively reads `_meta.appType` from `LoaderOptionsPlugin` to synchronize routing logic with the development server.
28
+
29
+ ### Fixed
30
+ - **Type Safety**: Improved Webpack 5 internal typing for asset emission using `sources.RawSource`.
31
+ - **Build Reliability**: Replaced `copy-webpack-plugin` for generated assets with a native Webpack emission strategy to prevent "file not found" errors during build.
32
+
33
+ ---
34
+
11
35
  ## [1.8.0] - 2026-03-13
12
36
 
13
37
  ### Added
package/README.md CHANGED
@@ -1,92 +1,62 @@
1
1
  # @razerspine/webpack-core
2
+
2
3
  [![npm version](https://img.shields.io/npm/v/@razerspine/webpack-core.svg)](https://www.npmjs.com/package/@razerspine/webpack-core)
3
4
  [![changelog](https://img.shields.io/badge/docs-changelog-blue.svg)](./CHANGELOG.md)
4
5
  [![license](https://img.shields.io/npm/l/@razerspine/webpack-core.svg)](./LICENSE)
5
6
 
6
-
7
7
  Core webpack configuration and loaders for **Pug-based** projects.
8
8
 
9
- This package provides a stable, production-safe webpack foundation for
10
- template-driven builds using `pug-plugin`.
9
+ This package provides a stable, production-safe webpack foundation for template-driven builds using `pug-plugin`, now
10
+ with **Smart Auto-Hosting** support.
11
11
 
12
12
  ---
13
13
 
14
- ## Designed for
15
-
16
- Part of the
17
- [Webpack Starter Monorepo](https://github.com/Razerspine/webpack-starter-monorepo).
14
+ ## 🚀 Key Features
18
15
 
19
- Can be used independently in any Pug-based project.
16
+ - **Pug template-driven builds**: Webpack JS entry is intentionally disabled.
17
+ - **Hybrid Modes**: Full support for Multi-page (MPA) and Single-page (SPA) architectures.
18
+ - **Smart Auto-Hosting (v1.9.0)**: Automatically detects **Vercel, Netlify, Cloudflare**, and **GitHub Pages** to
19
+ generate required routing configs.
20
+ - **Zero-Config SPA Fallback**: Automatic `404.html` generation for GitHub Pages to fix client-side routing.
21
+ - **Full Tech Stack**: Native support for TypeScript/JavaScript and SCSS/Less.
22
+ - **Developer Experience**: Recursive file watching (`src/**/*`), auto-browser open, and infrastructure logging.
23
+ - **Validation Layer**: Core options are validated and normalized before Webpack initialization.
20
24
 
21
25
  ---
22
26
 
23
- ## Key Features
24
-
25
- - Pug template-driven builds (no implicit JS entry)
26
- - Multi-page (MPA) and Single-page (SPA) modes
27
- - JavaScript or TypeScript support
28
- - SCSS or Less support
29
- - Recursive file watching (`src/**/*`)
30
- - SPA-friendly dev server
31
- - Config validation layer
32
- - Centralized options normalization (v1.7.1+)
33
- - Fully customizable dev & prod configs
34
- - **New (v1.8.0) Automatic Deployment Configs**: Generates `_redirects` and `vercel.json` automatically.
35
- - **New (v1.8.0) GitHub Pages SPA Support**: Automatic `404.html` fallback for single-page apps.
36
-
37
- ---
38
-
39
- ## Application Modes (v1.7.1+)
27
+ ## 🛠 Application Modes
40
28
 
41
29
  ### MPA (Default)
42
30
 
43
- ```js
44
- appType: 'mpa'
45
- ```
31
+ `appType: 'mpa'`
46
32
 
47
- - `templates.entry` must be a directory
48
- - Example: `src/views/pages`
49
- - Each page generates its own HTML file
33
+ - `templates.entry` must be a **directory** (e.g., `src/views/pages`).
34
+ - Each Pug file in the directory generates its own HTML file.
50
35
 
51
36
  ### SPA
52
37
 
53
- ```js
54
- appType: 'spa'
55
- ```
38
+ `appType: 'spa'`
56
39
 
57
- - `templates.entry` must be a single Pug file
58
- - Example: `src/views/app.pug`
59
- - Always outputs: `index.html`
40
+ - `templates.entry` must be a **single Pug file** (e.g., `src/app/app.pug`).
41
+ - Always outputs `index.html`.
42
+ - Enables automatic routing configuration for production hosting.
60
43
 
61
44
  ---
62
45
 
63
- ## Design Principles
64
-
65
- - **Webpack is responsible for**: module resolution, aliases (`resolve.alias`), and asset handling.
66
- - **Template-driven architecture**: Webpack JS entry is intentionally disabled. Builds are driven by Pug template entries.
67
- - **MPA by default**: Directory-based page generation remains the primary mode.
68
- - **Optional SPA support (v1.7.1+)**: Single-entry template mode is supported without breaking MPA workflow.
69
- - **Stability-first production defaults**: No aggressive optimizations (e.g. `splitChunks`) are enabled by default to prevent template asset resolution issues.
70
- - **Validated configuration layer**: Core options are validated before Webpack initialization.
71
- - **Centralized option normalization (v1.7.1+)**: Default resolution is handled internally through a normalization layer to avoid configuration drift.
72
- - **Flexible overrides**: Dev and Prod configs can be extended safely via optional parameters.
73
-
74
- ---
46
+ ## 🌍 Smart Hosting Adapter (New v1.9.0)
75
47
 
76
- ## Features
48
+ The core now detects the environment during the production build and emits the necessary configuration files:
77
49
 
78
- - **Pug templates support** with auto-discovery.
79
- - **JavaScript / TypeScript** integration.
80
- - **SCSS / Less** styling support.
81
- - **Recursive File Watching**: Dev server watches all changes in `src/**/*`.
82
- - **SPA-friendly Dev Server**: Integrated historyApiFallback (redirects to 404.html).
83
- - **Customizable**: Easily override devServer or optimization settings.
84
- - **Configuration validation layer**
85
- - **Automatic browser open in development (v1.2.2+)**
50
+ | Platform | Generated File | Purpose |
51
+ |:-------------------------|:---------------|:-------------------------------------------------------------|
52
+ | **Netlify / Cloudflare** | `_redirects` | Handles SPA rewrites and MPA fallbacks. |
53
+ | **Vercel** | `vercel.json` | Configures Vercel Edge Network routing. |
54
+ | **GitHub Pages** | `404.html` | Duplicates `index.html` to prevent 404 errors on deep links. |
55
+ | **Static / Others** | `404.html` | Generic fallback for SPA mode. |
86
56
 
87
57
  ---
88
58
 
89
- ## Installation
59
+ ## 📦 Installation
90
60
 
91
61
  ```bash
92
62
  npm install @razerspine/webpack-core
@@ -94,7 +64,7 @@ npm install @razerspine/webpack-core
94
64
 
95
65
  ---
96
66
 
97
- ## Usage
67
+ ## 📖 Usage
98
68
 
99
69
  ### Basic Setup
100
70
 
@@ -107,20 +77,20 @@ const {
107
77
  } = require('@razerspine/webpack-core');
108
78
 
109
79
  module.exports = (env = {}, argv = {}) => {
110
- const mode = argv.mode || 'development';
80
+ const mode = argv.mode || process.env.NODE_ENV || 'development';
111
81
 
112
82
  const baseConfig = createBaseConfig({
113
83
  mode,
114
- appType: 'mpa', // or 'spa'
115
- scripts: 'js', // or 'ts'
116
- styles: 'scss', // or 'less'
84
+ appType: 'spa', // 'spa' or 'mpa'
85
+ scripts: 'ts', // 'js' or 'ts'
86
+ styles: 'scss', // 'scss' or 'less'
117
87
  templates: {
118
- entry: 'src/views/pages',
88
+ entry: 'src/app/app.pug',
119
89
  },
120
90
  resolve: {
121
91
  alias: {
122
- '@views': path.resolve(process.cwd(), 'src/views'),
123
- '@styles': path.resolve(process.cwd(), 'src/assets/styles'),
92
+ '@app': path.resolve(process.cwd(), 'src/app'),
93
+ '@styles': path.resolve(process.cwd(), 'src/styles'),
124
94
  },
125
95
  },
126
96
  });
@@ -133,21 +103,20 @@ module.exports = (env = {}, argv = {}) => {
133
103
  };
134
104
  ```
135
105
 
136
- ### Customizing Configuration (v1.2.1+)
106
+ ### Customizing Configuration
137
107
 
138
- You can now pass an optional second argument to `createDevConfig` and `createProdConfig` to override defaults:
108
+ You can override any default setting by passing an object as the second argument:
139
109
 
140
110
  ```js
141
- // Customizing the Dev Server (port, open browser, etc.)
111
+ // Customizing the Dev Server
142
112
  if (mode === 'development') {
143
113
  return createDevConfig(baseConfig, {
144
114
  port: 3000,
145
115
  open: true,
146
- // extra devServer options...
147
116
  });
148
117
  }
149
118
 
150
- // Customizing Production (minification, performance hints, etc.)
119
+ // Customizing Production optimizations
151
120
  if (mode === 'production') {
152
121
  return createProdConfig(baseConfig, {
153
122
  performance: {
@@ -159,57 +128,13 @@ if (mode === 'production') {
159
128
 
160
129
  ---
161
130
 
162
- ## Architecture Principles
163
- - Webpack handles module resolution and asset processing
164
- - PugPlugin handles template compilation
165
- - No implicit webpack JS entry
166
- - No aggressive production optimizations by default
167
- - Options validated before build initialization
168
- - Defaults resolved through a normalization layer (v1.7.1+)
169
-
170
- ---
171
-
172
- ## Stability
173
-
174
- Versions prior to 1.1.6 were part of a stabilization phase and are not recommended for production use.
175
-
176
- ---
177
-
178
- ## API Reference
179
-
180
- `createBaseConfig(options)`
181
-
182
- Core configuration factory.
183
-
184
- **Options include**:
185
-
186
- - `mode` — `'development' | 'production'`
187
- - `scripts` — `'js' | 'ts'`
188
- - `styles` — `'scss' | 'less'`
189
- - `templates.entry` — Path to template pages directory
190
- - `resolve.alias` — Webpack aliases
191
-
192
- All options are validated before initialization.
193
-
194
- ---
195
-
196
- `createDevConfig(baseConfig, options?)`
197
-
198
- - `baseConfig`: The configuration returned by createBaseConfig.
199
- - `options`: (Optional) webpack-dev-server configuration object.
200
- - **Default behavior**: Watches `src/**/*`, uses port `8080`, and rewrites 404s to `/404.html`.
201
-
202
- ---
203
-
204
- `createProdConfig(baseConfig, options?)`
131
+ ## 🏗 Architecture Principles
205
132
 
206
- - `baseConfig`: The configuration returned by createBaseConfig.
207
- - `options`: (Optional) Webpack configuration object for production overrides.
208
- - **Default behavior**:
209
- - Enables source maps and minification.
210
- - Disables `splitChunks` for template compatibility.
211
- - **New**: Generates routing assets (`_redirects`, `vercel.json`) based on `appType`.
212
- - **New**: Creates `404.html` fallback for SPA mode.
133
+ - **Template-First**: Webpack handles assets, but Pug templates drive the entry points.
134
+ - **Stability-First**: Aggressive optimizations (like `splitChunks`) are disabled by default to ensure reliable asset
135
+ resolution in templates.
136
+ - **Environment Aware**: The build process is aware of CI/CD environments and adapts output artifacts accordingly.
137
+ - **Type Safe**: Improved internal typing for Webpack 5 asset emission.
213
138
 
214
139
  ---
215
140
 
@@ -3,40 +3,51 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createProdConfig = createProdConfig;
4
4
  const webpack_1 = require("webpack");
5
5
  const webpack_merge_1 = require("webpack-merge");
6
- function getRedirects(appType) {
7
- return appType === 'spa'
8
- ? '/* /index.html 200\n'
9
- : '/* /404.html 404\n';
10
- }
11
- function getVercelConfig(appType) {
12
- const config = appType === 'spa'
13
- ? { routes: [{ src: '/(.*)', dest: '/index.html' }] }
14
- : {
15
- routes: [
16
- { handle: 'filesystem' },
17
- { src: '/(.*)', dest: '/404.html', status: 404 }
18
- ]
19
- };
20
- return JSON.stringify(config, null, 2);
21
- }
6
+ const detect_hosting_1 = require("../utils/detect-hosting");
7
+ const get_vercel_config_1 = require("../utils/get-vercel-config");
8
+ const get_redirects_1 = require("../utils/get-redirects");
22
9
  function createProdConfig(baseConfig, options = {}) {
23
10
  var _a, _b, _c, _d, _e;
24
11
  const loaderPlugin = (_a = baseConfig.plugins) === null || _a === void 0 ? void 0 : _a.find((p) => p instanceof webpack_1.LoaderOptionsPlugin);
25
12
  const appType = (_e = (_d = (_c = (_b = loaderPlugin === null || loaderPlugin === void 0 ? void 0 : loaderPlugin.options) === null || _b === void 0 ? void 0 : _b.options) === null || _c === void 0 ? void 0 : _c._meta) === null || _d === void 0 ? void 0 : _d.appType) !== null && _e !== void 0 ? _e : 'mpa';
13
+ const hosting = (0, detect_hosting_1.detectHosting)();
26
14
  const routingPlugin = {
27
15
  apply(compiler) {
16
+ const logger = compiler.getInfrastructureLogger('@razerspine/webpack-core');
28
17
  compiler.hooks.thisCompilation.tap('RoutingPlugin', (compilation) => {
29
18
  compilation.hooks.processAssets.tap({
30
19
  name: 'RoutingPlugin',
31
20
  stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
32
21
  }, () => {
33
- const { RawSource } = webpack_1.sources;
34
- compilation.emitAsset('_redirects', new RawSource(getRedirects(appType)));
35
- compilation.emitAsset('vercel.json', new RawSource(getVercelConfig(appType)));
22
+ /**
23
+ * Netlify / Cloudflare
24
+ */
25
+ if (hosting === 'netlify' || hosting === 'cloudflare') {
26
+ logger.info(`📦 ${hosting.charAt(0).toUpperCase() + hosting.slice(1)} detected. Generating _redirects for ${appType.toUpperCase()}...`);
27
+ compilation.emitAsset('_redirects', new webpack_1.sources.RawSource((0, get_redirects_1.getRedirects)(appType)));
28
+ }
29
+ /**
30
+ * Vercel
31
+ */
32
+ if (hosting === 'vercel') {
33
+ logger.info(`📦 Vercel detected. Generating vercel.json for ${appType.toUpperCase()}...`);
34
+ compilation.emitAsset('vercel.json', new webpack_1.sources.RawSource((0, get_vercel_config_1.getVercelConfig)(appType)));
35
+ }
36
+ /**
37
+ * SPA fallback
38
+ * Needed for:
39
+ * - GitHub Pages
40
+ * - static hosting
41
+ */
36
42
  if (appType === 'spa') {
37
43
  const indexAsset = compilation.getAsset('index.html');
38
44
  if (indexAsset) {
39
- compilation.emitAsset('404.html', indexAsset.source);
45
+ const source = indexAsset.source.source().toString();
46
+ if (hosting === 'github' || hosting === 'static') {
47
+ const hostName = hosting === 'github' ? 'GitHub Pages' : 'Static hosting';
48
+ logger.info(`📦 ${hostName} detected. Creating 404.html fallback for SPA...`);
49
+ compilation.emitAsset('404.html', new webpack_1.sources.RawSource(source));
50
+ }
40
51
  }
41
52
  }
42
53
  });
package/dist/index.d.ts CHANGED
@@ -7,3 +7,4 @@ export * from './types/style-type';
7
7
  export * from './types/app-type';
8
8
  export * from './types/config-option-type';
9
9
  export * from './types/base-webpack-config-type';
10
+ export * from './types/hosting-type';
package/dist/index.js CHANGED
@@ -27,3 +27,4 @@ __exportStar(require("./types/style-type"), exports);
27
27
  __exportStar(require("./types/app-type"), exports);
28
28
  __exportStar(require("./types/config-option-type"), exports);
29
29
  __exportStar(require("./types/base-webpack-config-type"), exports);
30
+ __exportStar(require("./types/hosting-type"), exports);
@@ -0,0 +1 @@
1
+ export type HostingType = 'netlify' | 'vercel' | 'cloudflare' | 'github' | 'static';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import { HostingType } from '../types/hosting-type';
2
+ export declare function detectHosting(): HostingType;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectHosting = detectHosting;
4
+ function detectHosting() {
5
+ if (process.env.NETLIFY)
6
+ return 'netlify';
7
+ if (process.env.VERCEL)
8
+ return 'vercel';
9
+ if (process.env.CF_PAGES)
10
+ return 'cloudflare';
11
+ if (process.env.GITHUB_ACTIONS)
12
+ return 'github';
13
+ return 'static';
14
+ }
@@ -0,0 +1,2 @@
1
+ import { AppType } from '../types/app-type';
2
+ export declare function getRedirects(appType: AppType): string;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRedirects = getRedirects;
4
+ function getRedirects(appType) {
5
+ return appType === 'spa'
6
+ ? '/* /index.html 200\n'
7
+ : '/* /404.html 404\n';
8
+ }
@@ -0,0 +1,2 @@
1
+ import { AppType } from '../types/app-type';
2
+ export declare function getVercelConfig(appType: AppType): string;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVercelConfig = getVercelConfig;
4
+ function getVercelConfig(appType) {
5
+ const config = appType === 'spa'
6
+ ? {
7
+ routes: [
8
+ {
9
+ src: '/(.*)',
10
+ dest: '/index.html',
11
+ },
12
+ ],
13
+ }
14
+ : {
15
+ routes: [
16
+ {
17
+ handle: 'filesystem'
18
+ },
19
+ {
20
+ src: '/(.*)',
21
+ dest: '/404.html',
22
+ status: 404,
23
+ },
24
+ ],
25
+ };
26
+ return JSON.stringify(config, null, 2);
27
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@razerspine/webpack-core",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Core webpack config and loaders for starter templates",
5
5
  "keywords": [
6
6
  "webpack",