0.0.0-beta-20230905193120 • Published 8 months ago

vite-plugin-mono-source v0.0.0-beta-20230905193120

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

vite-plugin-mono-source

Using packages source code in monorepo with Vite, Seamless.

Why

When developing a Web application in a monorepo, after modifying the source code of a package, you need to rebuild the package and restart the application to see the effect. This is very inconvenient and lost the blazing HMR feature of Vite. With this plugin, you can use the source code of the package directly in the application.

Features

  1. Automatic source code resolve with HMR.
  2. Automatic TypeScript source code modification detection, IDE friendly.
  3. Cascaded sourcemap support.

Usage

Installation

npm i vite-plugin-mono-source -D

Example

import { defineConfig } from 'vite'
import { monorepoSrcPlugin } from 'vite-plugin-mono-source'

export default defineConfig({
  plugins: [
    monorepoSrcPlugin([
      {
        packages: ['@playground/*'],
        excludedPackages: ['@playground/lib-c'],
        entries: [
          { find: '', replacement: ['/src/index.ts', '/src/index.tsx'] },
          { find: /es\/(.*)/, replacement: ['/src/$1'] },
        ],
        emptyModules: ['/es/only-exist-in-build.css'],
      },
    ]),
  ],
})

In this example, we have a monorepo several packages build with tsc. packages matches all package's name that match glob pattern and exclude @playground/lib-c.

entries is a list of entries that will be resolved by Vite. find could be a string or a regex to find the rest subpath after package name. replacement is the path of the entry in the application. In the example, all bare package import will be resolved to /src/index.ts or /src/index.tsx. All import from es folder will be resolved to /src folder with the same rest subpath.

emptyModules is a list of modules that will be replaced with empty modules when resolving, this is useful when you have some modules that only exist in build time and has been achieved in development mode by application.

Configuration

export interface Mapping {
  /**
   * packages names to match, glob supported
   * if `packages` is provided, both `packagePaths` and `packages` will be used
   * to take the union
   */
  packages?: string[]
  /**
   * paths to match, glob supported, relative to the root of the monorepo
   * if `packages` is provided, both `packagePaths` and `packages` will be used
   * to take the union
   */
  packagePaths?: string[]
  /**
   * matches string after packages name
   * for example, give a single entry package:
   * if you want to replace `@monorepo/pkg` to `@monorepo/pkg/src/index.ts`
   * `mappings` could be set to
   *
   * ```ts
   * [{ find: '', replacement: ['src/index.ts'] }]
   * ```
   *
   * if given a multi entry package:
   * if you want to replace
   * `@monorepo/pkg` to `@monorepo/pkg/src/index.ts` and
   * `@monorepo/pkg/es/button` to `@monorepo/pkg/src/button.tsx`
   * `@monorepo/pkg/es/button/interface` to `@monorepo/pkg/src/button/interface.ts`
   * `mapping` could be set to be
   *
   * ```ts
   * [
   *   { find: '', replacement: ['src/index.ts'] },
   *   { find: /es/(.*)/, replacement: ['src/$1.tsx'] },
   * ]
   * ```
   */
  entries: Entries
  /** TODO */
  customResolver?: ResolverFunction | ResolverObject | null
  /**
   * packages to exclude, glob supported
   * if matched, the package will not be resolved anyway
   */
  excludedPackages?: string[]
  /**
   * paths to exclude, glob supported, relative to the root of the monorepo
   * if matched, the package will not be resolved anyway
   */
  excludedPackagePaths?: string[]
  /**
   * modules to ignore when resolving, it's useful when you want to ignore some
   * modules that not exists in development mode, glob supported.
   */
  emptyModules?: string[] | RegExp
}

export type Entry = {
  /**
   * string or regexp to match packages subpath without package name
   * for examples:
   * - `find: ''` will match `@monorepo/pkg-a` or `@monorepo/pkg-b`
   * - `find: /es/(.*)/` will match `@monorepo/pkg/es/button` and other paths matches the regexp
   */
  find: string | RegExp
  /**
   * replacement for the matched path, the first resolved path will be used, if all replacement
   * can't be resolved by Vite, the original importee will be used.
   * for examples:
   * - `{ find: '', replacement: ['/src/index.ts', '/src/index.tsx'] }`will replace `@monorepo/pkg-a` to `@monorepo/pkg-a/src/index.ts`
   * - `{ find: /es/(.*)/, replacement: ['/src/$1'] }` will replace `@monorepo/pkg/es/button` to `@monorepo/pkg/src/button.tsx`
   * using a function typed as `ReplaceFunction` is also supported to customize the replacement.
   */
  replacement: string[] | ReplaceFunction
}

export type ReplaceFunction = (args: ReplaceFunctionArgs) => string[]

export type ReplaceFunctionArgs = {
  subPath: string
  matchedPackage: Package
  importerTsconfig: TSConfckParseResult | null
}

export type Entries = Entry[]
export type MappingArray = readonly Mapping[]

export interface ResolvedMapping {
  matchedPackages: Package[]
  entries: Entries
  resolverFunction: ResolverFunction | null
  emptyModules: string[] | RegExp
}

export interface ResolveOptions {
  /**
   * automatically resolve tsconfig.compilerOptions.paths
   * @default true
   */
  resolveTsconfigPaths?: boolean
  /**
   * automatically resolve TypeScript project references
   * @default true
   */
  resolveProjectReferences: boolean
}
```

## License

[MIT](./LICENSE) License © 2023-PRESENT [fi3ework](https://github.com/fi3ework)