mkdist

repository·main·Indexed 19 days ago

https://github.com/unjs/mkdist

A lightweight file-to-file transformer designed for library distribution as an alternative to bundlers. mkdist preserves original file structures and modern syntax while providing support for Vue Single File Components, TypeScript declaration generation, and PostCSS integration. It utilizes esbuild for high-performance transformations and includes a CLI for specifying source/destination paths, module formats (cjs/esm), and glob patterns.

Tokens
6.1K
Snippets
20
Records
22
Agent score
66%

What's inside mkdist

  1. What is mkdist?

    main

    mkdist is a lightweight file-to-file transformer designed to process files while preserving their original structure. Unlike traditional bundlers, it avoids losing modern syntax or original file organization.

    Key features include:

    • Asset Preservation: Copies all assets automatically.
    • Vue Support: Handles Vue Single File Components (.vue).
    • High Performance: Uses esbuild for fast, minimal transformations.
    • Type Generation: Generates .d.ts declaration files for .ts, .js, and .vue files.
    • PostCSS Integration: Built-in support for postcss with autoprefixer, cssnano, and postcss-nested enabled by default.
  2. Configure LoaderOptions

    main

    The LoaderOptions object defines how files are transformed. These options are passed through the LoaderContext to individual loaders.

    Key configuration keys:

    • ext: Target extension (e.g., 'js' | 'mjs' | 'cjs' | 'ts' | 'mts' | 'cts').
    • format: Output module format ('cjs' | 'esm').
    • declaration: Boolean to enable/disable type declaration generation.
    • esbuild: Configuration object for esbuild (CommonOptions).
    • postcss: Configuration for PostCSS processing. Can be false or an object containing:
      • nested: Options for postcss-nested.
      • autoprefixer: Options for autoprefixer.
      • cssnano: Options for cssnano.
      • plugins: An array of PostcssPlugins.
      • processOptions: PostCSS process options (excluding the from key).
    const options: LoaderOptions = {
      format: 'esm',
      declaration: true,
      postcss: {
        autoprefixer: { flexbox: true },
        plugins: [/* custom postcss plugins */],
        processOptions: { syntax: 'scss' }
      },
      esbuild: {
        minify: true
      }
    };
  3. Configure mkdist build externals

    main

    When using unbuild to configure the mkdist build process, you can use the externals option to specify which dependencies should be treated as external and not bundled into the output. This is useful for preventing the inclusion of large or environment-specific packages like sass in your distribution.

    import { defineBuildConfig } from "unbuild";
    
    export default defineBuildConfig({
      externals: ["sass"]
    });
  4. Configure mkdist options

    main

    The MkdistOptions object allows you to control the transformation process.

    Directory Configuration

    • rootDir: The base directory for resolving paths (defaults to process.cwd()).
    • srcDir: The directory containing source files (defaults to src relative to rootDir).
    • distDir: The directory where output files will be written (defaults to dist relative to rootDir).

    File Selection

    • pattern: A glob pattern or array of patterns to match files in srcDir (defaults to **).
    • globOptions: Options passed directly to tinyglobby for file scanning.

    Transformation & Output

    • loaders: An array of LoaderName or Loader instances to use for file transformations.
    • cleanDist: Boolean indicating whether to delete the distDir before starting (defaults to true).
    • addRelativeDeclarationExtensions: Boolean to add relative extensions to declarations.
    • typescript: Configuration for TypeScript declaration emission.

    TypeScript Configuration

    Pass a typescript object containing compilerOptions to customize how .d.ts files are generated. mkdist applies several defaults to ensure compatibility with declaration-only emission (e.g., emitDeclarationOnly: true, declaration: true).

    const options: MkdistOptions = {
      rootDir: '.',
      srcDir: 'src',
      distDir: 'dist',
      pattern: ['**/*.ts', '**/*.vue'],
      cleanDist: true,
      loaders: ['ts', 'vue'], // Example using LoaderNames
      typescript: {
        compilerOptions: {
          strict: true
        }
      }
    };
  5. Configure ESLint with eslint-config-unjs

    main

    To use the standard UNJS linting configuration in your project, import eslint-config-unjs and export it as the default configuration in your eslint.config.mjs file. The configuration function accepts an options object that allows you to define global ignores, custom ESLint rules, and specific overrides for Markdown linting.

    import unjs from "eslint-config-unjs";
    
    export default unjs({
      ignores: ["**/dist/**"],
      rules: {
        "@typescript-eslint/no-empty-object-type": 0,
      },
      markdown: {
        rules: {
          // markdown rule overrides
        },
      },
    });
  6. Configure the PostCSS loader

    main

    The postcssLoader processes .css files using PostCSS. You can configure it via the postcss property in your mkdist options object.

    By default, the loader includes support for postcss-nested, autoprefixer, and cssnano, but these can be toggled or customized. If ctx.options.postcss is set to false, the loader is disabled.

    Available configuration keys within the postcss object:

    • nested: Boolean or PostCSS plugin options for postcss-nested. Defaults to enabled (unless explicitly set to false).
    • autoprefixer: Boolean or PostCSS plugin options for autoprefixer. Defaults to enabled.
    • cssnano: Boolean or PostCSS plugin options for cssnano. Defaults to enabled.
    • plugins: An array of additional PostCSS plugins to apply.
    • processOptions: An object containing options passed directly to the PostCSS .process() method (e.g., from, map).
    // Example configuration for mkdist options
    {
      postcss: {
        nested: true,
        autoprefixer: { grid: 'autoplace' },
        cssnano: true,
        plugins: [/* custom plugins */],
        processOptions: {
          // options passed to postcss.process()
        }
      }
    }
  7. Use the mkdist CLI

    main

    You can run mkdist using npx. The CLI allows you to specify a root directory, source/destination paths, glob patterns, and output formats.

    Command Syntax:

    npx mkdist [rootDir] [--src=src] [--dist=dist] [--no-clean] [--pattern=glob [--pattern=more-glob]] [--format=cjs|esm] [-d|--declaration] [--ext=mjs|js|ts]

    Options Reference:

    • [rootDir]: The root directory for the transformation.
    • --src=<path>: The source directory.
    • --dist=<path>: The output distribution directory.
    • --no-clean: Prevents the tool from cleaning the output directory before running.
    • --pattern=<glob>: A glob pattern to include specific files. You can provide multiple --pattern flags.
    • --format=<cjs|esm>: Specifies the module format (cjs or esm).
    • -d or --declaration: Enables .d.ts declaration file generation.
    • --ext=<mjs|js|ts>: Specifies the file extension for the output files.
  8. Configure custom block loaders for Vue SFCs

    main

    You can customize how specific blocks (like <script>, <style>, or custom blocks) are handled by using defineVueLoader. This allows you to intercept blocks and transform their content or extract them into separate files.

    DefineVueLoaderOptions accepts a blockLoaders object where keys are the block types (e.g., 'style', 'script', 'template') and values are VueBlockLoader functions.

    import { defineVueLoader, type DefineVueLoaderOptions } from 'mkdist/loaders/vue';
    
    const options: DefineVueLoaderOptions = {
      blockLoaders: {
        style: async (block, context) => {
          // 'block' contains { type, content, attrs }
          // 'context' provides access to loadFile and addOutput
          return block; // Return modified block or undefined to skip
        }
      }
    };
    
    const myLoader = defineVueLoader(options);
  9. Understand the mkdist return value

    main

    The mkdist function returns a Promise that resolves to an object containing the results of the operation:

    • writtenFiles: An array of absolute paths to the files successfully written to the distDir.
    • errors: An array of error objects. Each object contains:
      • filename: The absolute path of the file that encountered an error.
      • errors: An array of TypeError objects associated with that file.
    const { writtenFiles, errors } = await mkdist({
      srcDir: 'src',
      distDir: 'dist'
    });
    
    if (errors.length > 0) {
      console.error('Errors occurred:', errors);
    }
    
    console.log('Files written:', writtenFiles);
  10. Use the mkdist() function

    main

    The mkdist function is the primary entry point for transforming source files (like TypeScript or Vue) into a distribution directory (like ESM/CJS). It scans a source directory based on a pattern, applies loaders to transform files, resolves relative import paths to ensure compatibility with the output format, and writes the results to a distribution directory.

    By default, mkdist will clean the distDir before writing new files unless cleanDist: false is specified.

    import { mkdist } from 'mkdist';
    
    await mkdist({
      srcDir: 'src',
      distDir: 'dist',
      pattern: '**/*.ts'
    });
  11. Use the Vue Single File Component (SFC) loader

    main

    The vueLoader is the primary entry point for processing .vue files. It attempts to use vue-sfc-transformer/mkdist for advanced transformations (like TypeScript support). If that package is not installed, it automatically falls back to fallbackVueLoader.

    import { vueLoader } from 'mkdist/loaders/vue';
    
    // Use vueLoader within your mkdist configuration
    // It accepts (input: InputFile, context: LoaderContext)
  12. Use the loaders registry to resolve file loaders

    main

    The loaders object provides access to built-in loaders for specific file types. It includes js, sass, and postcss. The vue loader is loaded dynamically: it attempts to use vue-sfc-transformer/mkdist if available, otherwise it falls back to a default vueLoader.

    Available loader names (LoaderName):

    • js
    • vue
    • sass
    • postcss
    import { loaders } from 'mkdist/loaders';
    
    // Access a specific loader
    const jsLoader = loaders.js;
    const vueLoader = await loaders.vue;
    const sassLoader = loaders.sass;
    const postcssLoader = loaders.postcss;