@asd14/vblocks 1.0.0 → 2.0.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/LICENSE CHANGED
@@ -1,29 +1,21 @@
1
- BSD 3-Clause License
1
+ MIT License
2
2
 
3
- Copyright (c) 2025, Andrei Dumitrescu
4
- All rights reserved.
3
+ Copyright (c) 2025 Andrei Dumitrescu
5
4
 
6
- Redistribution and use in source and binary forms, with or without
7
- modification, are permitted provided that the following conditions are met:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
8
11
 
9
- 1. Redistributions of source code must retain the above copyright notice, this
10
- list of conditions and the following disclaimer.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
11
14
 
12
- 2. Redistributions in binary form must reproduce the above copyright notice,
13
- this list of conditions and the following disclaimer in the documentation
14
- and/or other materials provided with the distribution.
15
-
16
- 3. Neither the name of the copyright holder nor the names of its
17
- contributors may be used to endorse or promote products derived from
18
- this software without specific prior written permission.
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,18 +1,42 @@
1
- # vblocks
1
+ [![Release](https://github.com/asd-xiv/vblocks/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/asd-xiv/vblocks/actions/workflows/main.yml)
2
+ [![npm version](https://img.shields.io/npm/v/@asd14/vblocks.svg)](https://www.npmjs.com/package/@asd14/vblocks)
2
3
 
3
- > 📜 POSIX + 📦 Webpack, an unlikely story!
4
+ # @asd14/vblocks
4
5
 
5
- Zero-config Webpack wrapper for React applications with opinionated defaults and
6
- modern toolchain integration.
6
+ > 📜 POSIX + 📦 Webpack, an unlikely story!
7
7
 
8
8
  ## Features
9
9
 
10
- - **Zero Configuration** - Works out of the box with sensible defaults
11
- - **Convention over Configuration** - Smart project structure detection
12
- - **Modern Toolchain** - SWC, TailwindCSS, PostCSS, CSS Modules, MDX support
13
- - **Flexible Configuration** - Project configs override defaults when present
14
- - **Development Experience** - Hot reload, React Refresh, bundle analysis
15
- - **Production Ready** - Optimized builds with code splitting and caching
10
+ - **No configs** - All you need are `src/index.tsx` and `src/index.html`
11
+ - **Built in** - SWC for TypeScript, PostCSS, CSS Modules, MDX, React Refresh,
12
+ bundle analyzer
13
+
14
+ <!-- vim-markdown-toc GFM -->
15
+
16
+ - [Installation](#installation)
17
+ - [Peer Dependencies](#peer-dependencies)
18
+ - [Usage](#usage)
19
+ - [Quick Start](#quick-start)
20
+ - [Project Structure](#project-structure)
21
+ - [Configuration](#configuration)
22
+ - [Commands](#commands)
23
+ - [`vblocks init`](#vblocks-init)
24
+ - [`vblocks serve`](#vblocks-serve)
25
+ - [`vblocks build`](#vblocks-build)
26
+ - [`vblocks eject`](#vblocks-eject)
27
+ - [Features in Detail](#features-in-detail)
28
+ - [TypeScript](#typescript)
29
+ - [PostCSS](#postcss)
30
+ - [CSS Modules Support](#css-modules-support)
31
+ - [Asset Handling](#asset-handling)
32
+ - [Environment Variables](#environment-variables)
33
+ - [Path Alias](#path-alias)
34
+ - [How It Works](#how-it-works)
35
+ - [FAQ](#faq)
36
+ - [Does VBlocks support Tailwind?](#does-vblocks-support-tailwind)
37
+ - [License](#license)
38
+
39
+ <!-- vim-markdown-toc -->
16
40
 
17
41
  ## Installation
18
42
 
@@ -20,170 +44,381 @@ modern toolchain integration.
20
44
  npm install --save-dev @asd14/vblocks
21
45
  ```
22
46
 
47
+ > [!IMPORTANT]
48
+ > VBlocks needs Node `^22.22.3`, `^24.15.0` or `>=26.0`.
49
+
50
+ ### Peer Dependencies
51
+
52
+ ```sh
53
+ npm install react react-dom
54
+ ```
55
+
56
+ > [!IMPORTANT]
57
+ > VBlocks needs React `^18` or `^19`.
58
+
23
59
  ## Usage
24
60
 
25
61
  ### Quick Start
26
62
 
63
+ Create a project and start the dev server:
64
+
65
+ ```sh
66
+ npx @asd14/vblocks init my-app
67
+ cd my-app
68
+ npm install
69
+ npm start
70
+ ```
71
+
72
+ Run a command in a project that has VBlocks installed:
73
+
27
74
  ```sh
28
- # Start development server
75
+ # Start the dev server
29
76
  npx vblocks serve
30
77
 
31
78
  # Build for production
32
79
  npx vblocks build
33
80
 
34
- # View webpack configuration
81
+ # Print the default Webpack config
35
82
  npx vblocks eject webpack
36
83
  ```
37
84
 
38
85
  ### Project Structure
39
86
 
40
- VBlocks expects a standard React project structure:
41
-
42
- ```
87
+ ```text
43
88
  your-project/
44
89
  ├── src/
45
90
  │ ├── index.tsx # Application entry point
46
91
  │ ├── index.html # HTML template
47
- │ ├── index.css # Global styles (optional)
92
+ │ ├── index.css # Global CSS (optional)
48
93
  │ └── public/
49
94
  │ ├── favicon.svg # Favicon (optional)
50
- │ └── robots.txt # Robots file (optional)
95
+ │ └── robots.txt # Crawler instructions (optional)
51
96
  ├── .env # Environment variables (optional)
52
97
  └── dist/ # Build output
53
98
  ```
54
99
 
55
- ## How It Works
100
+ ## Configuration
56
101
 
57
- VBlocks is a **POSIX shell script wrapper** around Webpack that:
102
+ A config in your project root replaces the default of the same name.
58
103
 
59
- 1. **Detects configuration files** - Uses project configs when available, falls
60
- back to defaults
61
- 2. **Sets environment variables** - Passes config paths to Webpack via env vars
62
- 3. **Proxies commands** - `build` and `serve` are passed directly to `webpack`
63
- with custom parameters
64
- 4. **Provides configuration inspection** - `eject` outputs configuration content
65
- for review
104
+ - `webpack.config.js`
105
+ - `postcss.config.js`
106
+ - `.swcrc`
66
107
 
67
- ## Configuration
108
+ To replace a default, first [`eject`](#vblocks-eject) it into your project root,
109
+ then edit the file:
68
110
 
69
- VBlocks follows a **configuration hierarchy** - project files take precedence
70
- over defaults:
111
+ ```sh
112
+ npx vblocks eject postcss > postcss.config.js
113
+ ```
71
114
 
72
- 1. **Project configs** (in your project root) - highest priority
73
- 2. **Default configs** (from vblocks package) - fallback
115
+ > [!NOTE]
116
+ > VBlocks does not merge your config with the default, with two exceptions:
117
+ >
118
+ > - `.swcrc -> env.targets`: VBlocks adds the default when yours has none
119
+ > - `.swcrc -> jsc.transform.react.refresh`: VBlocks adds the React Refresh
120
+ > transform when `serve` runs in `development` mode
74
121
 
75
- ### Supported Configuration Files
122
+ ## Commands
76
123
 
77
- - `webpack.config.js` - Webpack configuration
78
- - `postcss.config.js` - PostCSS configuration
79
- - `tailwind.config.js` - TailwindCSS configuration
80
- - `.swcrc` - SWC configuration
124
+ ### `vblocks init`
81
125
 
82
- ### Configuration Override Example
126
+ ```text
127
+ vblocks init <directory> [--template <name>]
128
+ ```
83
129
 
84
- Create any of these files in your project root to customize behavior:
130
+ Creates a project in `<directory>` from a template.
85
131
 
86
- ```js
87
- // tailwind.config.js - customize TailwindCSS
88
- export default {
89
- content: ["./src/**/*.{ts,tsx}"],
90
- theme: {
91
- extend: {
92
- colors: {
93
- primary: "#your-color"
94
- }
95
- }
96
- }
97
- }
132
+ | Parameter | Required | Default | Description |
133
+ | ------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------ |
134
+ | `<directory>` | yes | none | The project root. `init` creates it when it is missing and fails when it exists and is not empty |
135
+ | `--template <name>` | no | `plain` | The template to copy: `plain` or `xyflow-playground` |
136
+
137
+ | Template | `src/index.tsx` | `dependencies` | Tailwind |
138
+ | ------------------- | ------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
139
+ | `plain` | Hello World! | `react`, `react-dom` | no |
140
+ | `xyflow-playground` | Renders a graph of nodes you can drag and connect | `react`, `react-dom`, [`@xyflow/react`](https://reactflow.dev) | yes, `package.json`, `postcss.config.js` and `src/index.css` hold [the setup](#does-vblocks-support-tailwind) |
141
+
142
+ `init` writes:
143
+
144
+ ```text
145
+ <directory>/
146
+ ├── src/
147
+ │ ├── index.tsx # Application entry point
148
+ │ ├── index.html # HTML template
149
+ │ └── index.css # Global CSS
150
+ ├── .gitignore # node_modules, dist, .env
151
+ ├── package.json
152
+ ├── postcss.config.js # Only in xyflow-playground
153
+ └── tsconfig.json
98
154
  ```
99
155
 
100
- ## Commands
156
+ Run `init` through `npx @asd14/vblocks`. `init` installs no dependencies, so
157
+ install them next:
158
+
159
+ ```sh
160
+ npx @asd14/vblocks init my-flow --template xyflow-playground
161
+ cd my-flow
162
+ npm install
163
+ ```
101
164
 
102
165
  ### `vblocks serve`
103
166
 
104
- **Proxies to**:
105
- `npx webpack serve --config $VB_WEBPACK_CONFIG --env entryDir=$PROJECT_DIR ...`
167
+ ```text
168
+ vblocks serve [--mode <mode>] [<webpack option>...]
169
+ ```
170
+
171
+ Starts the dev server. Without `--port`, it listens on `http://localhost:8080`.
172
+
173
+ | Parameter | Required | Default | Description |
174
+ | ------------------ | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
175
+ | `--mode <mode>` | no | `development` | The Webpack mode, `development` or `production`. React Refresh runs only in `development` |
176
+ | `<webpack option>` | no | none | Any other [`webpack serve`](https://webpack.js.org/configuration/dev-server/) option, eg. `--port 3000` or `--no-open`. VBlocks passes it to Webpack unchanged |
106
177
 
107
- Starts development server with:
178
+ The dev server:
108
179
 
109
- - Hot Module Replacement
110
- - Automatic browser opening
111
- - Bundle analyzer (non-opening)
112
- - Error overlay
113
- - History API fallback for SPAs
180
+ - Replaces changed modules without a page reload, with Hot Module Replacement
181
+ and React Refresh
182
+ - Opens the browser
183
+ - Runs the bundle analyzer at `http://127.0.0.1:8888`. VBlocks does not open it
184
+ in the browser
185
+ - Serves `index.html` for every unknown path, for applications that use the
186
+ History API
187
+
188
+ **Runs**:
189
+
190
+ ```sh
191
+ npx webpack serve --config <webpack config> \
192
+ --env entryDir=<project root> \
193
+ --mode development \
194
+ [...your arguments]
195
+ ```
114
196
 
115
197
  ### `vblocks build`
116
198
 
117
- **Proxies to**:
118
- `npx webpack build --config $VB_WEBPACK_CONFIG --env entryDir=$PROJECT_DIR ...`
199
+ ```text
200
+ vblocks build [--mode <mode>] [--env single] [<webpack option>...]
201
+ ```
202
+
203
+ Builds the project into `dist/`.
204
+
205
+ | Parameter | Required | Default | Description |
206
+ | ------------------ | -------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
207
+ | `--mode <mode>` | no | `production` | The Webpack mode, `development` or `production`. The build minifies JS, CSS and HTML only in `production` |
208
+ | `--env single` | no | off | Build one standalone `dist/index.html` |
209
+ | `<webpack option>` | no | none | Any other [`webpack build`](https://webpack.js.org/api/cli/) option, eg. `--stats errors-only`. VBlocks passes it to Webpack unchanged |
119
210
 
120
- Creates production build with:
211
+ Without `--env single`, the build:
121
212
 
122
- - Minified assets
123
- - Content hashing
124
- - Optimized chunks
125
- - Performance hints
213
+ - Writes JS and CSS files with content-hashed names
214
+ - Writes a `react` chunk, and a `vendors` chunk when your other dependencies
215
+ total over 20 KB
126
216
 
127
- ### `vblocks eject webpack`
217
+ With `--env single`:
128
218
 
129
- **Special command** - Outputs the webpack configuration to stdout for
130
- inspection:
219
+ - `dist/index.html` holds every script, stylesheet, image, font and the favicon
220
+ - A browser opens the file from disk, with no server and no network
221
+ - Keep the route in the URL hash. On `file://`, `history.pushState` to another
222
+ path throws
223
+
224
+ **Runs**:
225
+
226
+ ```sh
227
+ npx webpack build --config <webpack config> \
228
+ --env entryDir=<project root> \
229
+ --mode production \
230
+ [...your arguments]
231
+ ```
232
+
233
+ ### `vblocks eject`
234
+
235
+ ```text
236
+ vblocks eject <config>
237
+ ```
238
+
239
+ Prints a default config to stdout.
240
+
241
+ | Parameter | Required | Default | Description |
242
+ | ---------- | -------- | ------- | -------------------------------------------------- |
243
+ | `<config>` | yes | none | The config to print: `webpack`, `postcss` or `swc` |
244
+
245
+ Save the output in your project root to [replace the default](#configuration):
131
246
 
132
247
  ```sh
133
248
  npx vblocks eject webpack > webpack.config.js
249
+ npx vblocks eject postcss > postcss.config.js
250
+ npx vblocks eject swc > .swcrc
134
251
  ```
135
252
 
136
253
  ## Features in Detail
137
254
 
255
+ ### TypeScript
256
+
257
+ VBlocks does not check types and never reads your `tsconfig.json`. It only
258
+ compiles TypeScript with SWC.
259
+
260
+ For convenience, VBlocks provides client types in
261
+ [`client.d.ts`](src/types/client.d.ts) for:
262
+
263
+ - `.css` imports
264
+ - Image and font imports
265
+ - `process.env`
266
+
267
+ You can use them in your `tsconfig.json`:
268
+
269
+ ```json
270
+ {
271
+ "compilerOptions": {
272
+ "types": ["@asd14/vblocks/client"]
273
+ }
274
+ }
275
+ ```
276
+
277
+ `tsc` needs the [`@self`](#path-alias) path alias in your `tsconfig.json`:
278
+
279
+ ```diff
280
+ {
281
+ "compilerOptions": {
282
+ "types": ["@asd14/vblocks/client"],
283
+ + "paths": { "@self/*": ["./src/*"] }
284
+ }
285
+ }
286
+ ```
287
+
288
+ The `tsconfig.json` that [`vblocks init`](#vblocks-init) writes has both.
289
+
290
+ ### PostCSS
291
+
292
+ The default `postcss.config.js`:
293
+
294
+ ```js
295
+ /**
296
+ * @param {{ mode: "production" | "development" | "none" }} api
297
+ */
298
+ export default ({ mode }) => ({
299
+ plugins: {
300
+ "postcss-preset-env": {
301
+ stage: 2,
302
+ },
303
+ "cssnano": mode === "production" && {
304
+ preset: "default",
305
+ },
306
+ },
307
+ })
308
+ ```
309
+
310
+ `postcss-preset-env` compiles nesting, `oklch()` and `color-mix()` for older
311
+ browsers and adds vendor prefixes.
312
+
138
313
  ### CSS Modules Support
139
314
 
140
- - **Global CSS** - `import './styles.css'`
141
- - **Local CSS Modules** - `import styles from './component.module.css'`
315
+ - **Global CSS** - `import "./styles.css"`
316
+ - **Local CSS Modules** - `import styles from "./component.module.css"`
142
317
  - **camelCase exports** - `.my-class` becomes `styles.myClass`
143
- - **Development-friendly naming** - includes class names in dev builds
318
+ - **Class names** - a bare hash in `production` mode, `[local]__[hash]` in
319
+ `development` mode
320
+ - **TypeScript** - the [client types](#typescript) declare `.css` imports
144
321
 
145
322
  ### Asset Handling
146
323
 
147
- - **Images** - Automatic optimization, inlined if < 10KB
148
- - **Fonts** - Copied to `fonts/` directory
149
- - **Favicon & Robots** - Automatically included in build
324
+ - **Images** - the build inlines `jpg`, `gif`, `png` and `svg` files up to 10 KB
325
+ - **Fonts** - the build writes `woff`, `woff2`, `ttf` and `eot` files to
326
+ `dist/fonts/`
327
+ - **Favicon and `robots.txt`** - yours or the default. `--env single` leaves
328
+ `robots.txt` out
150
329
 
151
330
  ### Environment Variables
152
331
 
153
- VBlocks automatically loads `.env` files in your project root:
332
+ VBlocks loads the `.env` file in your project root:
154
333
 
155
334
  ```env
156
- # .env
157
- REACT_APP_API_URL=https://api.example.com
335
+ API_URL=https://api.example.com
158
336
  ```
159
337
 
160
- Access in your code:
338
+ Read a variable in your code:
161
339
 
162
340
  ```tsx
163
- const apiUrl = process.env.REACT_APP_API_URL
341
+ const apiUrl = process.env["API_URL"]
164
342
  ```
165
343
 
166
- ### Path Aliases
344
+ Webpack replaces each `process.env` read with the variable's value. A variable
345
+ that `.env` does not set reads as `undefined`. The build leaves out every
346
+ variable your code does not read.
347
+
348
+ The [client types](#typescript) declare `process.env` and nothing else from
349
+ Node, because Webpack replaces nothing else. With the client types, `tsc` fails
350
+ on `process.cwd()` and `Buffer`.
167
351
 
168
- Built-in alias for cleaner imports:
352
+ ### Path Alias
353
+
354
+ `@self` points at your `src/` directory:
169
355
 
170
356
  ```tsx
171
- // Instead of: import { Component } from '../../../components'
357
+ // Instead of: import { Component } from "../../../components"
172
358
  import { Component } from "@self/components"
173
359
  ```
174
360
 
175
- ## Peer Dependencies
361
+ `tsc` needs the same alias in your `tsconfig.json`. See
362
+ [TypeScript](#typescript).
176
363
 
177
- ```json
178
- {
179
- "peerDependencies": {
180
- "react": "^18 || ^19",
181
- "react-dom": "^18 || ^19"
182
- }
183
- }
364
+ ## How It Works
365
+
366
+ VBlocks is a POSIX shell script that runs Webpack. The script exports
367
+ `VB_POSTCSS_CONFIG` and `VB_SWC_CONFIG`, the paths of the configs it picked. The
368
+ Webpack config reads them.
369
+
370
+ ## FAQ
371
+
372
+ ### Does VBlocks support Tailwind?
373
+
374
+ Yes, VBlocks supports Tailwind but does not include it, so you need a
375
+ `postcss.config.js` in your project root.
376
+
377
+ 1. Install Tailwind and the Tailwind plugin for PostCSS:
378
+
379
+ ```sh
380
+ npm install --save-dev tailwindcss @tailwindcss/postcss
184
381
  ```
185
382
 
186
- ## License
383
+ 2. Eject the default PostCSS config into your project root:
384
+
385
+ ```sh
386
+ npx vblocks eject postcss > postcss.config.js
387
+ ```
388
+
389
+ 3. Replace `postcss-preset-env` with the Tailwind plugin:
390
+
391
+ ```diff
392
+ export default ({ mode }) => ({
393
+ plugins: {
394
+ - "postcss-preset-env": {
395
+ - stage: 2,
396
+ - },
397
+ + "@tailwindcss/postcss": {
398
+ + optimize: mode === "production",
399
+ + },
400
+ "cssnano": mode === "production" && {
401
+ preset: "default",
402
+ },
403
+ },
404
+ })
405
+ ```
187
406
 
188
- BSD 3-Clause
407
+ > [!IMPORTANT]
408
+ > You do not need `postcss-preset-env`. Tailwind 4
409
+ > [compiles nesting and adds vendor prefixes](https://tailwindcss.com/docs/compatibility)
410
+ > itself. With both plugins, `postcss-preset-env` rewrites Tailwind's `@layer`
411
+ > rules into `:not(#\#)` selectors. The CSS file grows.
412
+
413
+ 4. Add this import to `src/index.css`:
414
+
415
+ ```css
416
+ @import "tailwindcss";
417
+ ```
418
+
419
+ The `xyflow-playground` template of [`vblocks init`](#vblocks-init) has this
420
+ setup.
421
+
422
+ ## License
189
423
 
424
+ MIT