diff --git a/docs/guide/build-mode.en-US.md b/docs/guide/build-mode.en-US.md new file mode 100644 index 00000000..4d852759 --- /dev/null +++ b/docs/guide/build-mode.en-US.md @@ -0,0 +1,99 @@ +# Build Modes + +## Bundless + +Bundless is a file-to-file build mode that does not process dependencies but instead compiles source files in parallel. Some popular community tools like [tsc](https://www.typescriptlang.org/docs/handbook/compiler-options.html), [unbuild](https://github.com/unjs/unbuild), and the older Babel mode of father use this approach for building. + +In father 4, both ESModule and CommonJS outputs use the Bundless build mode. Let's take a look at how father works in this mode. + +Given the following source structure: + +```bash +. +└── src + ├── index.less + ├── index.tsx +    └── util.js +``` + +With the following build configuration: + +```js +export default { + esm: { output: 'dist' }, + // or + cjs: { output: 'dist' }, +}; +``` + +father will generate the following output: + +```bash +. +└── dist + ├── index.d.ts + ├── index.js + ├── index.less +    └── util.js +``` + +### How Bundless Works + +In Bundless mode, father processes the source files as follows: + +1. TypeScript files are compiled into JavaScript files, with corresponding `.d.ts` type definitions. +2. JavaScript files are compiled into JavaScript with compatibility adjustments. +3. Other files (such as stylesheets) are copied directly without modification. + +### When to Choose Bundless + +Bundless builds allow selective imports and provide better debugging capabilities. For most projects, Bundless is the preferred choice, which is why it is widely adopted in the community. + +For details on choosing between ESModule and CommonJS outputs, refer to the [ESModule vs CommonJS](./esm-cjs.md#how-to-choose) guide. + +--- + +## Bundle + +Bundle mode packages the source files by starting from an entry file, recursively resolving dependencies, and merging everything into a final build output. Tools like [Webpack](https://webpack.js.org), [Rollup](https://rollupjs.org/guide/en/), and the older Rollup mode of father follow this approach. + +In **father 4**, the Bundle build mode is only used for UMD outputs. Let's see how it works. + +Given the following source structure: + +```bash +. +└── src + ├── index.less + └── index.tsx # Imports index.less +``` + +With the following build configuration: + +```ts +export default { + umd: { output: 'dist' }, +}; +``` + +father will generate: + +```bash +. +└── dist + ├── index.min.js + └── index.min.css +``` + +### How Bundle Works + +In Bundle mode, father processes the source files by: + +- Bundling all dependencies into a single output file. +- Generating minified JavaScript and CSS assets for optimized delivery. + +### When to Choose Bundle + +Bundle mode produces self-contained outputs. Since father only uses Bundle mode for UMD builds, choosing UMD automatically means using the Bundle mode. + +For guidance on when to choose UMD outputs, refer to the [UMD Build Guide](./umd.md#how-to-choose). \ No newline at end of file diff --git a/docs/guide/dev.en-US.md b/docs/guide/dev.en-US.md new file mode 100644 index 00000000..c81a6ce9 --- /dev/null +++ b/docs/guide/dev.en-US.md @@ -0,0 +1,27 @@ +# Development + +Once the build configuration is set up, you can start development. + +## Real-Time Compilation + +During development, real-time compilation is needed for debugging and verification: + +```bash +# Start real-time compilation +$ father dev +# Skip the initial full build and only perform incremental builds on file changes +$ father dev --incremental +``` + +Whenever source files or configuration changes, the output will be incrementally compiled in real-time. + +## Debugging in a Project + +To test in another project, use `npm link` to link your project for debugging and verification: + +```bash +$ cd test-project +$ npm link /path/to/your-father-project . +``` + +Once development and testing are complete, you can proceed with [publishing](./release.md) the NPM package. \ No newline at end of file diff --git a/docs/guide/doctor.en-US.md b/docs/guide/doctor.en-US.md new file mode 100644 index 00000000..b666c221 --- /dev/null +++ b/docs/guide/doctor.en-US.md @@ -0,0 +1,88 @@ +# Project Inspection + +Father's project inspection feature helps identify potential issues and provides improvement suggestions. Simply run: + +```bash +$ father doctor +``` + +The following rules are currently included. + +## PACK_FILES_MISSING + +- Severity: Error ❌ +- Description: + +The `files` field is configured in `package.json`, but the build output directory is missing. This can cause the published NPM package to lack the necessary modules. + +## EFFECTS_IN_SIDE_EFFECTS + +- Severity: Error ❌ +- Description: + +The `sideEffects` field in `package.json` is misconfigured. Common mistakes include: + +1. The build output includes style files, but `sideEffects` is set to `false`, causing styles to be lost after project compilation. +2. Using Rollup.js-incompatible patterns like `*.css`. In Webpack, this matches all CSS files, but in Rollup.js, it only matches top-level CSS files. + +## PHANTOM_DEPS + +- Severity: Error ❌ +- Description: + +A dependency is used in the source code but is not declared in `dependencies`. This results in a [phantom dependency](https://rushjs.io/pages/advanced/phantom_deps/)—it may not exist or could be the wrong version, leading to runtime failures. + +## CASE_SENSITIVE_PATHS + +- Severity: Error ❌ +- Description: + +The file path casing in imports does not match the actual file names on disk. This issue is often unnoticed on case-insensitive file systems (e.g., Windows, macOS default settings), but it can cause module resolution failures on case-sensitive systems after publishing to NPM. + +## TSCONFIG_RISK + +- Severity: Error ❌ +- Description: + +Checks for risks in `tsconfig.json`. Currently, the following risk is detected: + +1. If `compilerOptions.declaration` is enabled and `include` does not cover any Bundless build source files, `.d.ts` files may be missing in the output, triggering an error. + +## PREFER_PACK_FILES + +- Severity: Warning ⚠️ +- Description: + +It is recommended to use the `files` field to specify which files to publish to NPM, reducing package size. + +## PREFER_NO_CSS_MODULES + +- Severity: Warning ⚠️ +- Description: + +Avoid using CSS Modules, as they make it difficult for users to override styles and add extra compilation overhead. + +## PREFER_BABEL_RUNTIME + +- Severity: Warning ⚠️ +- Description: + +Installing `@babel/runtime` in `dependencies` is recommended to reduce the build output size. + +> Note: This rule only applies when `transformer` is `babel` and `platform` is `browser`. + +## DUP_IN_PEER_DEPS + +- Severity: Warning ⚠️ +- Description: + +The same dependency appears in both `peerDependencies` and `dependencies`. It is recommended to remove one based on the project's needs. + +If you have additional recommendations for NPM package development, feel free to comment on [this issue](https://github.com/umijs/father-next/issues/36). If approved, the rule will be added. + +## PREFER_PEER_DEPS + +- Severity: Warning ⚠️ +- Description: + +Dependencies that could cause multiple instances (e.g., `react`, `antd`) should be placed in `peerDependencies` instead of `dependencies`. \ No newline at end of file diff --git a/docs/guide/esm-cjs.en-US.md b/docs/guide/esm-cjs.en-US.md new file mode 100644 index 00000000..ba1a0dd8 --- /dev/null +++ b/docs/guide/esm-cjs.en-US.md @@ -0,0 +1,44 @@ +# Building ESModule and CommonJS Outputs + +> In the Father project, ESModule and CommonJS output builds follow a similar process, so they are covered together in this chapter. + +## How to Choose + +ESModule is the module standard for JavaScript, while CommonJS is used by Node.js. To determine which output format your project needs, consider the usage scenario: + +| Output Type / Runtime | Browser | Node.js | Both | +| ---------------------- | ------- | -------- | ------- | +| ESModule | ✅ Recommended | Not Recommended Yet | ✅ Recommended | +| CommonJS | Not Necessary | ✅ Recommended | ✅ Recommended | + +Additional Notes + +1. The push for Pure ESM in the Node.js community still faces [some challenges](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). For broader compatibility, it is still recommended to produce CommonJS outputs for Node.js projects. In the future, Father will introduce a compatibility solution for generating both ESModule and CommonJS outputs. +2. For browser environments, CommonJS output is unnecessary since all modern module bundlers can handle ESModules. With the rise of tools like Vite that support native ESModules, using ESModule is the best future-proof approach. +3. Both means the output is intended for use in both browser and Node.js environments, such as `react-dom` and `umi`. + +## How to Build + +Use the `esm` and `cjs` configuration options, then run `father build` to generate ESModule and CommonJS outputs: + +```js +// .fatherrc.js +export default { + // Default values for the `esm` config (only override if needed) + esm: { + input: 'src', // Default compilation directory + platform: 'browser', // Outputs for browser environments by default + transformer: 'babel', // Uses Babel for better compatibility + }, + // Default values for the `cjs` config (only override if needed) + cjs: { + input: 'src', // Default compilation directory + platform: 'node', // Outputs for Node.js environments by default + transformer: 'esbuild', // Uses esbuild for faster build speeds + }, +}; +``` + +For more configuration options, refer to the [Configuration Guide](../config.md). + +In the Father project, both ESModule and CommonJS outputs are built using the Bundless mode. For details on Bundless mode, see [Build Modes - Bundless](./build-mode.md#bundless). \ No newline at end of file diff --git a/docs/guide/guide.en-US.md b/docs/guide/guide.en-US.md new file mode 100644 index 00000000..723b05af --- /dev/null +++ b/docs/guide/guide.en-US.md @@ -0,0 +1 @@ +The documentation has been moved to [./guide/index.md](./guide/index.md). \ No newline at end of file diff --git a/docs/guide/index.en-US.md b/docs/guide/index.en-US.md index 045be8ff..2c4e46f5 100644 --- a/docs/guide/index.en-US.md +++ b/docs/guide/index.en-US.md @@ -2,10 +2,10 @@ ## Introduction -**Father** is an NPM package development tool that helps developers efficiently and reliably develop NPM packages, generate build artifacts, and publish them. It offers the following key features: +Father is an NPM package development tool that helps developers efficiently and reliably develop NPM packages, generate build artifacts, and publish them. It offers the following key features: -- ⚔️ **Dual-mode Build**: Supports both **Bundless** and **Bundle** build modes—ESModule and CommonJS outputs use Bundless mode, while UMD outputs use Bundle mode. -- 🎛 **Multiple Build Engines**: Bundle mode uses **Webpack** as the build engine, while Bundless mode supports **esbuild, Babel, and SWC**, allowing flexible configuration switching. +- ⚔️ **Dual-mode Build**: Supports both Bundless and Bundle build modes—ESModule and CommonJS outputs use Bundless mode, while UMD outputs use Bundle mode. +- 🎛 **Multiple Build Engines**: Bundle mode uses Webpack as the build engine, while Bundless mode supports esbuild, Babel, and SWC, allowing flexible configuration switching. - 🔖 **Type Generation**: Supports generating `.d.ts` type definitions for TypeScript modules, whether for source code builds or dependency pre-bundling. - 🚀 **Persistent Caching**: All output types support persistent caching, enabling faster incremental builds. - 🩺 **Project Inspection**: Checks for common pitfalls in NPM package development to ensure more stable releases. - @@ -14,17 +14,17 @@ --- -#### **Compatibility** +#### Compatibility -- **Father** requires **Node.js v14 or later** to run. Please ensure that you have Node.js **v14+** installed before using it. -- The **default Node.js output** from Father is compatible with **Node.js v14+**. -- **Browser output** is compatible with **ES5 (IE11)** by default. +- Father requires Node.js v14 or later to run. Please ensure that you have Node.js v14+ installed before using it. +- The default Node.js output from Father is compatible with Node.js v14+. +- Browser output is compatible with ES5 (IE11) by default. --- -#### **Quick Start** +#### Quick Start -Use `create-father` to quickly create a new **Father** project: +Use `create-father` to quickly create a new Father project: ```sh npx create-father my-father-project @@ -38,17 +38,17 @@ To build the project, run: npx father build ``` -After the build completes, check the `dist` folder to see the generated output. **Congratulations!** 🎉 You've successfully built your first Father project! +After the build completes, check the `dist` folder to see the generated output. Congratulations! 🎉 You've successfully built your first Father project! --- -#### **Next Steps** +#### Next Steps -Explore more features of **Father**: -- **Bundless vs. Bundle build modes** -- **Building ESModule & CommonJS outputs** -- **Building UMD outputs** -- **Dependency pre-bundling** -- **Running project inspections** -- **Development guide** -- **Publishing guide** +Explore more features of Father: +- Bundless vs. Bundle build modes +- Building ESModule & CommonJS outputs +- Building UMD outputs +- Dependency pre-bundling +- Running project inspections +- Development guide +- Publishing guide diff --git a/docs/guide/migrate.en-US.md b/docs/guide/migrate.en-US.md new file mode 100644 index 00000000..f0ed26dd --- /dev/null +++ b/docs/guide/migrate.en-US.md @@ -0,0 +1,200 @@ +# Upgrade from Father v2 or Father-Build v1 + +> Note: Father v2 = Father-Build v1 + documentation capabilities + other engineering enhancements. The build functionality remains the same. + +Follow these steps to manually upgrade your component library from Father v2 or Father-Build v1 to Father 4. + +## Breaking Changes + +1. **Rollup build mode is no longer supported.** + - If your source code needs bundling, output a UMD build (Webpack-based). + - If bundling is unnecessary, output ESModule (ESM) or CommonJS (CJS) using Bundless mode (Babel/esbuild-based). + - See [Build Modes](./build-mode.md) for details. + +2. **CSS Modules are no longer supported.** + - Using CSS Modules in a component library makes styles difficult to override and adds compilation overhead to user projects. + +3. **Bundless mode no longer compiles non-JavaScript files.** + - Let actual projects handle stylesheet compilation for better flexibility. + - If your component library requires custom themes, consider outputting a UMD build instead. See [UMD Build - How to Choose](./umd.md#how-to-choose). + +4. **Built-in documentation solutions are removed.** + - If you used **Docz**, migrate to Dumi ([Migration Guide](https://github.com/umijs/father/issues/241)). + - New projects should use the [Dumi Component Development Scaffold](https://d.umijs.org/zh-CN/guide#%E8%84%9A%E6%89%8B%E6%9E%B6%E5%88%9D%E5%A7%8B%E5%8C%96). + - Future versions of Dumi 2 and Father 4 will provide an integrated component development solution. + +5. **Monorepo support is no longer built-in.** + - Use Father 4 with your monorepo's own setup. + - Example: pnpm workspace users can refer to [Umi 4’s repository](https://github.com/umijs/umi). + +## `package.json` Upgrade + +```diff +{ + "scripts": { ++ "dev": "father dev", + "build": "father build", + ... + }, + "devDependencies": { + ... +- "father": "^2.0.0" ++ "father": "^4.0.0" + } +} +``` + +## Configuration File Upgrade + +- Switch from `.fatherrc.js` to `.fatherrc.ts` for better auto-completion. +- Update configurations accordingly: + +```diff ++ import { defineConfig } from 'father'; + +- export default { ++ export default defineConfig({ + ... +- } ++ }); +``` + +### Deprecated Configurations + +```diff +export default defineConfig({ + cjs: { + # Removed - Bundless mode does not need output files +- file: 'xxx', + # Removed - No longer configurable +- lazy: true, + # Removed - Bundless mode does not minify +- minify: true, + }, + esm: { + # Removed - Bundless mode does not need output files +- file: 'xxx', + # Removed - Will be replaced with a simpler pure ESM solution +- mjs: true, + # Removed - Bundless mode does not minify +- minify: true, + }, + umd: { + # Removed - Automatically reuses entry filename; use chainWebpack if needed +- file: 'xxx', + # Removed - Generates a minified version by default +- minFile: true, + # Temporarily unsupported; use chainWebpack if needed +- sourcemap: true, + }, + # Removed - No longer configurable +- cssModules: true, + # Removed - Type checking is always enabled +- disableTypeCheck: true, + # Removed - Migrate to Dumi +- doc: {}, + # Removed - No longer configurable +- file: 'xxx', + # Removed - Bundless mode no longer compiles non-JavaScript files +- lessInBabelMode: {}, + # Removed - Defaults to Node.js v14 compatibility +- nodeVersion: 14, + # Removed - Now automatic if @babel/runtime is in dependencies +- runtimeHelpers: true, + # Removed - Extracting CSS is now default; use chainWebpack for exceptions +- extractCSS: true, +- injectCSS: true, + # Removed - Monorepo is no longer handled +- pkgFilter: {}, +- pkgs: [], + # Removed - Rollup-specific configurations are unsupported +- extraRollupPlugins: [], +- include: {}, +- lessInRollupMode: {}, +- nodeResolveOpts: {}, +- sassInRollupMode: {}, +}); +``` + +### Updated Configurations + +```diff +export default defineConfig({ + // String values are no longer supported; use an object instead +- esm: 'babel', + esm: { + # Replaced with alias: { 'antd/lib': 'antd/es' } +- importLibToEs: true, + # Use the transformer property instead (see docs) +- type: 'rollup', + # Default is dist/esm; specify output if needed ++ output: 'es' + }, + // String values are no longer supported; use an object instead +- cjs: 'babel', + cjs: { + # Use the transformer property instead (see docs) +- type: 'rollup', + # Default output is node; set to browser if needed ++ platform: 'browser', + # Default is dist/cjs; specify output if needed ++ output: 'lib' + }, + umd: { + # Replaced with externals property +- globals: {}, + # Default is dist/umd; specify output if needed ++ output: 'dist' + }, + # UMD-only - Move to umd: { autoprefixer: {} } +- autoprefixer: {}, + # UMD-only - Move to umd: { entry: 'xxx' } +- entry: 'xxx', + # UMD-only - Move to umd: { postcssOptions: { plugins: [] } } +- extraPostCSSPlugins: [] + # UMD-only - Move to umd: { entry: { 'src/xx': {} } } +- overridesByEntry: {}, + # Replaced with platform property +- target: 'node', + # Use esm/cjs: { overrides: {}, ignores: [] } instead +- browserFiles: [], +- nodeFiles: [], + # UMD-only - Move to umd: { externals: {} } +- externalsExclude: {}, +- extraExternals: {}, + # Replaced with define property +- inject: {}, +- replace: {}, +}); +``` + +## Other Feature Updates + +### Testing + +- **Built-in test support is removed.** +- Use `father g jest` to generate test configurations. + +### Pre-Commit Hooks + +- **No longer included by default.** +- Use `father g lint`, `father g commitlint`, etc., to generate pre-commit scripts. + + +1. Copy old build artifacts from `node_modules` into your project. +2. Commit them as a temporary Git snapshot. +3. Run `father build` with the new configuration and ensure it compiles successfully. +4. Use `git diff` to compare old vs. new artifacts. + - If no logical differences (except Babel helper imports), the upgrade is successful. +5. Reset the temporary commit. + +### If using Rollup mode before upgrade: + +1. Run `father build` with the new configuration and ensure successful compilation. +2. Validate artifacts using a test project: + - Follow [Debugging in a Project](./dev.md#debugging-in-a-project). + - If the functionality remains intact, the upgrade is complete. + +Congratulations! 🎉 + +You've successfully upgraded to Father 4! 🚀 diff --git a/docs/guide/pre-bundle.en-US.md b/docs/guide/pre-bundle.en-US.md new file mode 100644 index 00000000..e00a6b7f --- /dev/null +++ b/docs/guide/pre-bundle.en-US.md @@ -0,0 +1,38 @@ +# Dependency Pre-Bundling (Experimental) + +> Note: Dependency pre-bundling is **only applicable to Node.js projects** and should not be used for browser-based projects. + +Dependency pre-bundling refers to compiling a project's dependencies, including their transitive dependencies, in advance as part of the project’s build output. The project's source code is then modified to import dependencies directly from the pre-bundled output. + +This approach has gained popularity in the Node.js community in recent years and provides several key benefits: + +1. **Smaller installation size and faster install speed for published NPM packages.** + An NPM package's dependency tree is often highly complex—while we may only depend on package A, the installation process might pull in an entire forest of dependencies, many of which are unnecessary. Pre-bundling consolidates these dependencies into a single file, reducing the overall package size and installation time. + +2. **Improved project stability.** + Many developers have encountered situations where "everything worked fine yesterday, but it's broken today." Even if upstream dependencies are carefully updated, they cannot guarantee compatibility across all use cases. Some dependencies might not even follow semantic versioning (semver). Pre-bundling allows us to take control of dependency updates—only updating them when we choose to re-bundle—significantly improving project stability. + +3. **Zero warnings when installing the published NPM package.** + The NPM installation process performs `peerDependencies` validation, which can generate many warnings. Since pre-bundled dependencies are included in the package, users will no longer see these warnings. However, as package maintainers, we can still review them during development. + +Despite its advantages, dependency pre-bundling can be complex. Challenges include handling `dynamic require/import` statements and accessing adjacent files in the bundled output. These issues can lead to pre-bundling failures or unusable results. + +Father has implemented extensive handling for these cases, but pre-bundling remains an **experimental feature**. Use it with caution, and report any issues in the [GitHub issue tracker](https://github.com/umijs/father-next/issues/28) to help improve the tool. + +For further reading, check out this related [article by YK](https://mp.weixin.qq.com/s/KbmpzvoB1yJlNDEO1p_fJQ) on dependency locking. + +## How to Build + +Simply enable the `prebundle` option and run `father prebundle` to generate the pre-bundled output: + +```js +// .fatherrc.js +export default { + prebundle: { + deps: ['pkg-a', 'pkg-b'], // Dependencies to pre-bundle (must be installed in `devDependencies`) + output: 'compiled', // Default output directory (customize only if necessary) + }, +}; +``` + +For more configuration options, refer to the [Configuration Guide](../config.md). \ No newline at end of file diff --git a/docs/guide/release.en-Us.md b/docs/guide/release.en-Us.md new file mode 100644 index 00000000..27de1d26 --- /dev/null +++ b/docs/guide/release.en-Us.md @@ -0,0 +1,46 @@ +# Publishing + +A standard NPM package can typically be published in just four steps. For monorepo projects, please refer to the specific publishing practices of your monorepo setup. + +## Prerequisites + +1. Run `npm whoami` to check if you are logged in. If not, log in using `npm login`. +2. Verify that the package name and publishConfig fields in `package.json` match your expectations. + +## Updating the Version Number + +Use the `npm version` command to increment the version number, for example: + +```bash +# Publish a patch version +$ npm version patch -m "build: release %s" +``` + +This command will automatically create a Git tag, commit the change, and update the version in `package.json`. +For more details, refer to the official NPM documentation: [npm version command](https://docs.npmjs.com/cli/v8/commands/npm-version). + +## Build and Publish + +Father 4's CLI automatically includes the [Project Health Check](./doctor.md) and build command in the `prepublishOnly` script: + +```diff + "scripts": { + ... ++ "prepublishOnly": "father doctor && npm run build" + }, +``` + +This means you only need to run the publish command: + +```bash +# NPM will automatically execute the prepublishOnly script before publishing +$ npm publish +``` + +## Post-Publish Tasks + +1. **Functionality Validation:** Use a test project to install the newly published NPM package and verify that it works as expected. +2. **Update Release Notes:** + - Document the changes in the GitHub Releases page. + - Alternatively, add them to `CHANGELOG.md` before publishing. + - (Father will soon support automated changelog generation—stay tuned!) \ No newline at end of file diff --git a/docs/guide/umd.en-US.md b/docs/guide/umd.en-US.md new file mode 100644 index 00000000..25c56655 --- /dev/null +++ b/docs/guide/umd.en-US.md @@ -0,0 +1,30 @@ +# Building UMD Bundles + +## When to Use UMD Output + +You should generate a UMD (Universal Module Definition) bundle only if one of the following conditions applies: + +1. Your users need to treat the package as an external dependency + - They might want to include it directly in an HTML file using a `