Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
783 changes: 739 additions & 44 deletions package-lock.json

Large diffs are not rendered by default.

157 changes: 152 additions & 5 deletions packages/vite-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

Vite configuration used by the WordPress team for sites and packages.

**To do:**

- Update Vite to 7.0.0 (check all dev dependencies for compatibility).

## Installation

```bash
Expand All @@ -30,7 +26,7 @@ export default braveConfig( {
'resources/scripts/editor/editor.js',
'resources/scripts/frontend/frontend.js',
'resources/styles/editor.css',
'resources/styles/frontend.css',
'resources/styles/frontend.css'
],
} );
```
Expand Down Expand Up @@ -84,3 +80,154 @@ export default defineConfig(
braveBlocksConfig({ blockPath: process.env.BLOCK_PATH })
);
```

## Package Vite configs

Presets for npm and Laravel packages. Both wrappers use `createBasePackageConfig`.

### Scripts in package.json

```json
{
"scripts": {
"start": "vite build --watch",
"build": "vite build",
"test": "vitest"
}
}
```

### laravelPackageConfig

```js
import { laravelPackageConfig } from '@yardinternet/vite-config';

export default laravelPackageConfig( {
entryPoints: {
index: 'src/index.ts',
},
} );
```

### npmPackageConfig

Assuming package name is `@yardinternet/gallery`, the config would look like this:

```js
import { npmPackageConfig } from '@yardinternet/vite-config';

export default npmPackageConfig( {
entryPoints: {
gallery: 'src/index.ts',
},
} );

// or with multiple entry points:
export default npmPackageConfig( {
entryPoints: {
frontend: 'src/frontend.ts',
editor: 'src/editor.ts',
},
} );
```


#### Reference build files in package.json

Package configs are ESM-only. Use `exports` as the public API for JS entry points and CSS, and add `types` plus `sideEffects` for TypeScript and safe CSS bundling.

Single entry point:

```json
{
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/gallery.js"
},
"./styles": "./dist/gallery.css"
},
"sideEffects": ["**/*.css"]
}
```
This allows consumers to import JS and CSS like this:

```js
import { Gallery } from '@yardinternet/gallery'; // imports gallery.js
import '@yardinternet/gallery/styles'; // imports gallery.css
```
...or import the CSS in CSS:
```css
@import '@yardinternet/gallery/styles'; /* imports gallery.css */
```

Multiple entry points:

```json
{
"type": "module",
"exports": {
".": {
"types": "./dist/frontend.d.ts",
"import": "./dist/frontend.js"
},
"./editor": {
"types": "./dist/editor.d.ts",
"import": "./dist/editor.js"
},
"./styles": "./dist/gallery.css"
},
"sideEffects": ["**/*.css"]
}
```
This allows consumers to import like this:

```js
import { Gallery } from '@yardinternet/gallery'; // imports frontend.js
import { Editor } from '@yardinternet/gallery/editor'; // imports editor.js
import '@yardinternet/gallery/styles'; // imports frontend.css
```

### All options

Both `npmPackageConfig` and `laravelPackageConfig` pass options through to the shared base package config.

```js
createBasePackageConfig( {
entryPoints,
outDir = 'dist',
externals = [],
formats = [ 'es' ],
fileName = defaultFileName,
packageJsonValidation = false,
test = {},
manifest = false,
plugins = [],
externalizeReact = true,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Het is wellicht goed om dit in de documentatie nog wat toe te lichten, voor het geval dat er wellicht ooit onverklaarbare bugs ontstaan omdat react niet gevonden kan worden

wordpressGlobals = true,
} )
```

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `entryPoints` | `Record<string, string> \| string[] \| string` | Required | Entry file(s) for the package build. Supports named object entries (recommended), array entries, or a single entry path. |
| `outDir` | `string` | `'dist'` | Build output directory. |
| `externals` | `string[]` | `[]` | Additional Rollup externals that should not be bundled. |
| `formats` | `Array<'es' \| 'cjs' \| 'umd' \| 'iife'>` | `[ 'es' ]` | Vite library output formats. Package preset is ESM. |
| `fileName` | `(format: string, entryName: string) => string` | `defaultFileName` | Controls emitted JS filenames per format and entry. |
| `packageJsonValidation` | `boolean` | `false` | When `true`, validates package.json output fields against configured entries. |
| `test` | `object` | `{}` | Merged into Vitest config. Default test environment is `jsdom`. |
| `manifest` | `boolean \| string` | `false` | Enables Vite manifest generation for Vite Laravel helper (`true` for default path, or a string for custom path). |
| `plugins` | `Array<import('vite').PluginOption>` | `[]` | Extra Vite plugins appended after built-in package plugins. |
| `externalizeReact` | `boolean` | `true` | Externalizes React, ReactDOM, and `react/jsx-runtime` to globals (`React`, `ReactDOM`, `ReactJSXRuntime`). |
| `wordpressGlobals` | `boolean` | `true` | Enables `@roots/vite-plugin` WordPress globals transform for `@wordpress/*` imports. |

Notes:

- All resolved entry files must exist. The config throws if any entry path is missing.
- In watch mode (`WATCH=true` or `vite build --watch`), source maps are inline, minification is disabled, and `emptyOutDir` is disabled to improve iteration.




1 change: 1 addition & 0 deletions packages/vite-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"laravel-vite-plugin": "^2.1.0",
"postcss-prefixwrap": "^1.57.2",
"vite-plugin-checker": "^0.12.0",
"vite-plugin-dts": "^4.5.4",
"vite-plugin-externals": "^0.6.2"
},
"peerDependencies": {
Expand Down
122 changes: 122 additions & 0 deletions packages/vite-config/src/configs/base-package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/**
* External dependencies
*/
import { defineConfig } from 'vite';
import { viteExternalsPlugin } from 'vite-plugin-externals';
import { wordpressPlugin } from '@roots/vite-plugin';
import dts from 'vite-plugin-dts';
import fs from 'fs';

/**
* Internal dependencies
*/
import {
getPackageJson,
validatePackageOutputFields,
} from '../utils/package-json.js';
import {
toEntryObject,
toAbsoluteEntries,
defaultFileName,
createAssetFileNames,
} from '../utils/package-helpers.js';

export const createBasePackageConfig = ( {
entryPoints,
outDir = 'dist',
externals = [],
formats = [ 'es' ],
fileName = defaultFileName,
packageJsonValidation = false,
test = {},
manifest = false,
plugins = [],
externalizeReact = true,
wordpressGlobals = true,
} = {} ) => {
const cwd = process.cwd();
const normalizedEntries = toEntryObject( entryPoints );
const absoluteEntries = toAbsoluteEntries( normalizedEntries, cwd );
const hasMissingEntry = Object.values( absoluteEntries ).some(
( entryPath ) => ! fs.existsSync( entryPath )
);

if ( hasMissingEntry ) {
throw new Error(
'[vite-config] One or more entry points do not exist.'
);
}

const resolvedFormats =
Array.isArray( formats ) && formats.length > 0 ? formats : [ 'es' ];
const primaryEntryName = Object.keys( normalizedEntries )[ 0 ];
const hasTsEntries = Object.values( absoluteEntries ).some( ( entry ) =>
/\.tsx?$/.test( entry )
);
const isWatchMode =
process.env.WATCH === 'true' || process.argv.includes( '--watch' );

return defineConfig( async () => {
const { packageJson } = getPackageJson( cwd );

if ( packageJsonValidation ) {
validatePackageOutputFields( {
entryName: primaryEntryName,
entryNames: Object.keys( normalizedEntries ),
formats: resolvedFormats,
outDir,
packageJson,
} );
}

return {
plugins: [
/**
* Externalizes React, ReactDOM and ReactJSXRuntime & reference global versions
* provided by WordPress' wp-element (window.React, window.ReactDOM)
*/
externalizeReact &&
viteExternalsPlugin( {
react: 'React',
'react-dom': 'ReactDOM',
'react/jsx-runtime': 'ReactJSXRuntime',
} ),
/**
* Transforms @wordpress/ dependencies to reference window.wp global
*/
wordpressGlobals && wordpressPlugin(),
]
.filter( Boolean )
.concat( [ hasTsEntries && dts(), ...plugins ] ),
test: {
environment: 'jsdom',
...test,
Comment thread
YvetteNikolov marked this conversation as resolved.
},
build: {
outDir,
lib: {
entry: absoluteEntries,
formats: resolvedFormats,
fileName,
},
assetsInlineLimit: 0,
manifest,
target: 'esnext',
sourcemap: isWatchMode ? 'inline' : false,
minify: ! isWatchMode,
emptyOutDir: ! isWatchMode,
rollupOptions: {
external: externals,
treeshake: true,
output: {
chunkFileNames: ( chunkInfo ) =>
`chunks/${ chunkInfo.name }.[hash].js`,
assetFileNames: createAssetFileNames( {
withHash: Boolean( manifest ),
} ),
},
},
},
};
} );
};
8 changes: 8 additions & 0 deletions packages/vite-config/src/configs/laravel-package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createBasePackageConfig } from './base-package.js';

export const laravelPackageConfig = ( options = {} ) =>
createBasePackageConfig( {
outDir: 'public',
manifest: true,
...options,
} );
8 changes: 8 additions & 0 deletions packages/vite-config/src/configs/npm-package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createBasePackageConfig } from './base-package.js';

export const npmPackageConfig = ( options = {} ) =>
createBasePackageConfig( {
outDir: 'dist',
packageJsonValidation: true,
...options,
} );
11 changes: 10 additions & 1 deletion packages/vite-config/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import { braveConfig } from './configs/brave.js';
import { braveBlocksConfig } from './configs/brave-theme-blocks.js';
import { createBasePackageConfig } from './configs/base-package.js';
import { npmPackageConfig } from './configs/npm-package.js';
import { laravelPackageConfig } from './configs/laravel-package.js';

export { braveConfig, braveBlocksConfig };
export {
braveBlocksConfig,
braveConfig,
createBasePackageConfig,
laravelPackageConfig,
npmPackageConfig,
};
5 changes: 5 additions & 0 deletions packages/vite-config/src/packages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createBasePackageConfig } from './configs/base-package.js';
import { npmPackageConfig } from './configs/npm-package.js';
import { laravelPackageConfig } from './configs/laravel-package.js';

export { createBasePackageConfig, npmPackageConfig, laravelPackageConfig };
4 changes: 1 addition & 3 deletions packages/vite-config/src/utils/generate-aliases.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import path from 'path';
* Generates the aliases for each theme to use like `@theme-name`.
* Example: `background-image: url('@sage/images/logo.svg')`; or `import '@sage-child/scripts/frontend/frontend.js';`
*/
const generateAliases = ( themeNames ) => {
export const generateAliases = ( themeNames ) => {
const themesDir = path.resolve( process.cwd(), 'web/app/themes' );
const aliases = {};

Expand All @@ -27,5 +27,3 @@ const generateAliases = ( themeNames ) => {

return aliases;
};

export { generateAliases };
Loading