What is esbuild-plugin-copy?
The esbuild-plugin-copy npm package is a plugin for esbuild that allows you to copy files and directories during the build process. This can be useful for tasks such as copying static assets, configuration files, or other resources that need to be included in the final build output.
What are esbuild-plugin-copy's main functionalities?
Copying Files
This feature allows you to copy individual files from a source directory to a destination directory during the build process. In this example, all files in the './src/assets/' directory are copied to the './dist/assets/' directory.
const esbuild = require('esbuild');
const copy = require('esbuild-plugin-copy');
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
plugins: [
copy({
assets: {
from: './src/assets/*',
to: './dist/assets/'
}
})
]
}).catch(() => process.exit(1));
Copying Directories
This feature allows you to copy entire directories while preserving the directory structure. In this example, the './src/public' directory and its contents are copied to the './dist/public' directory.
const esbuild = require('esbuild');
const copy = require('esbuild-plugin-copy');
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
plugins: [
copy({
assets: {
from: './src/public',
to: './dist/public',
keepStructure: true
}
})
]
}).catch(() => process.exit(1));
Customizing Copy Behavior
This feature allows you to customize the copy behavior for different files or directories. In this example, the './src/config.json' file is copied to './dist/config.json', and all files in the './src/images/' directory are copied to './dist/images/' with the overwrite option enabled.
const esbuild = require('esbuild');
const copy = require('esbuild-plugin-copy');
esbuild.build({
entryPoints: ['src/index.js'],
bundle: true,
outdir: 'dist',
plugins: [
copy({
assets: [
{ from: './src/config.json', to: './dist/config.json' },
{ from: './src/images/*', to: './dist/images/', options: { overwrite: true } }
]
})
]
}).catch(() => process.exit(1));
Other packages similar to esbuild-plugin-copy
copy-webpack-plugin
The copy-webpack-plugin is a similar plugin for Webpack that copies files and directories during the build process. It offers similar functionality to esbuild-plugin-copy but is designed to work with Webpack instead of esbuild.
rollup-plugin-copy
The rollup-plugin-copy is a plugin for Rollup that provides similar file and directory copying capabilities. It allows you to copy assets during the build process, similar to esbuild-plugin-copy, but is tailored for use with Rollup.
gulp-copy
The gulp-copy plugin is used with Gulp to copy files and directories as part of a Gulp task. It offers similar functionality to esbuild-plugin-copy but is designed to be used within the Gulp task runner ecosystem.
esbuild-plugin-copy
ESBuild plugin for assets copy.
Features
- Keep copied assets file structure
- Control assets destination path freely
- Support verbose output log
- Run only once or only when assets changed
Usage
npm install esbuild-plugin-copy --save-dev
pnpm install esbuild-plugin-copy --save-dev
yarn add esbuild-plugin-copy --save-dev
import { build } from 'esbuild';
import { copy } from 'esbuild-plugin-copy';
(async () => {
const res = await build({
entryPoints: ['./src/main.ts'],
bundle: true,
watch: true,
outfile: './dist/main.js',
plugins: [
copy({
resolveFrom: 'cwd',
assets: {
from: ['./assets/*'],
to: ['./assets', './tmp-assets'],
},
watch: true,
}),
],
});
})();
Keep file structure
import { copy } from 'esbuild-plugin-copy';
import { build } from 'esbuild';
(async () => {
const res = await build({
entryPoints: ['./src/index.ts'],
bundle: true,
outfile: './dist/main.js',
watch: true,
plugins: [
copy({
assets: [
{
from: ['./node_modules/tinymce/skins/**/*'],
to: ['./dest/skins'],
},
],
}),
],
});
})();
File structure will be kept:
|-node_modules/tinymce/skins
|--- content
|----- dark
|----- default
|----- document
|--- ui
|----- oxide
|----- oxide-dark
|- dist/dest/skins
|--- content
|----- dark
|----- default
|----- document
|--- ui
|----- oxide
|----- oxide-dark
You can also use patterns with extension names like ./path/**/*.js
.
File Glob
Note: This plugin doesnot expand directories by default, which means when you're using pattern dir/*
or dir/*.*
, you will only get the file inside dir/
like dir/index.md
. If you want to match the nested files like dir/path/to/index.md
, you will need to use pattern like dir/**/*
.
If you're using dir/*
and there are no files under this directory, you will got an warning:
i No files matched using current glob pattern: ./node_modules/tinymce/skins/*, maybe you need to configure globby by options.globbyOptions?
Watching Mode
You can use watch
option to enable watching mode
, which means this plugin will only copy files when assets changed. Also, you can control using watch mode
for all assets pair or only for some of them.
Watching Mode of this plugin is implemented using polling for being consistent with ESBuild Watch Mode, you could change the behavior by setting watch
option which will be passed to chokidar
under the hood.
Note: To use watching mode
, you must also enable ESBuild.build.watch
option.
Note: Watching Mode
only works for files outside ESBuild.build.absWorkingDir
, as if the files inside absWorkingDir
changed, ESBuild will re-execute plugin completely so we cannot choose file to copy.
(async () => {
const res = await build({
watch: true,
plugins: [
copy({
assets: [
{
from: [],
to: [],
watch: false,
},
],
}),
],
});
})();
(async () => {
const res = await build({
watch: false,
plugins: [
copy({
assets: [
{
from: [],
to: [],
watch: {
},
},
],
}),
],
});
})();
Configurations
import type { GlobbyOptions } from 'globby';
import type { WatchOptions } from 'chokidar';
export type MaybeArray<T> = T | T[];
export interface AssetPair {
from: MaybeArray<string>;
to: MaybeArray<string>;
watch?: boolean | WatchOptions;
}
export interface Options {
assets: MaybeArray<AssetPair>;
copyOnStart: boolean;
verbose: boolean;
globbyOptions: GlobbyOptions;
once: boolean;
resolveFrom: 'cwd' | 'out' | (string & {});
dryRun?: boolean;
watch?: boolean | WatchOptions;
}