clipboard-copy、copy-to-clipboard、ngclipboard、react-copy-to-clipboard、vue-clipboard2 はすべて、Webアプリケーションでテキストをユーザーのクリップボードにコピーする機能を提供するnpmパッケージです。これらのライブラリは、ネイティブの document.execCommand('copy') や現代的な navigator.clipboard.writeText() API をラップし、クロスブラウザ対応やユーザーエクスペリエンスの向上を目的としています。ただし、それぞれが異なるフレームワークやユースケースに最適化されており、アーキテクチャ上の選択肢として重要な違いがあります。
Webアプリで「コピー」ボタンを実装する際、多くの開発者は document.execCommand('copy') の複雑さやブラウザ間の差異に直面します。ここで紹介する5つのnpmパッケージは、その課題を解決するために設計されていますが、それぞれが異なるアプローチとトレードオフを持っています。以下では、実際のコード例を交えながら、技術的な違いと選定基準を詳しく見ていきます。
clipboard-copyこのパッケージは、単一の関数をエクスポートする軽量モジュールです。引数として文字列を受け取り、Promiseを返します。
import copy from 'clipboard-copy';
async function handleCopy() {
try {
await copy('コピーしたいテキスト');
console.log('コピー成功');
} catch (err) {
console.error('コピー失敗', err);
}
}
内部で navigator.clipboard.writeText() を使用し、それが利用できない環境では一時的な <textarea> 要素を作成してフォールバックします。依存関係がなく、どのフレームワークでも使えます。
copy-to-clipboardこちらも関数ベースですが、より詳細な制御が可能です。オプションでフォールバック動作を調整できます。
import copy from 'copy-to-clipboard';
// 成功/失敗をbooleanで返す(非Promise)
const success = copy('テキスト', {
debug: true, // デバッグログ出力
message: 'Cmd+C to copy' // フォールバック時のヒントメッセージ
});
if (success) {
console.log('コピー成功');
}
Promiseを返すオプションはありませんが、navigator.clipboard の可用性に応じて自動的に最適な方法を選択します。
ngclipboardAngular向けのディレクティブとして動作します。テンプレート内で属性として使用します。
// app.module.ts
import { NgClipboardModule } from 'ngclipboard';
@NgModule({
imports: [NgClipboardModule]
})
export class AppModule {}
<!-- template.html -->
<button ngClipboard [cbContent]="'コピー対象の文字列'">コピー</button>
ただし、Angular 9以降では公式の @angular/cdk/clipboard が推奨されており、ngclipboard はメンテナンスが停滞している可能性があるため、新規プロジェクトでの使用は避けるべきです。
react-copy-to-clipboardReactコンポーネントとして提供され、子要素をラップして使用します。
import { CopyToClipboard } from 'react-copy-to-clipboard';
function App() {
const [copied, setCopied] = useState(false);
return (
<CopyToClipboard text="コピーしたいテキスト" onCopy={() => setCopied(true)}>
<button>{copied ? 'コピー済み' : 'コピー'}</button>
</CopyToClipboard>
);
}
内部で copy-to-clipboard を呼び出しているため、React特有の抽象レイヤーが追加されるだけです。シンプルな実装には便利ですが、パフォーマンスに極端に敏感なケースでは直接 copy-to-clipboard を使う方が効率的です。
vue-clipboard2Vue 2向けのプラグインで、ディレクティブ経由で使用します。
// main.js
import Vue from 'vue';
import VueClipboard from 'vue-clipboard2';
Vue.use(VueClipboard);
<template>
<button v-clipboard:copy="message" v-clipboard:success="onCopySuccess">
コピー
</button>
</template>
<script>
export default {
data() {
return { message: 'コピーしたいテキスト' };
},
methods: {
onCopySuccess() {
alert('コピー成功!');
}
}
};
</script>
Vue 3では動作しないため、Vue 3プロジェクトでは @vueuse/core の useClipboard を使用することを強く推奨します。
現代のブラウザでは、navigator.clipboard.writeText() はユーザーの明示的な操作(例:クリック)がトリガーである場合にのみ許可されます。すべてのライブラリがこの制約を尊重していますが、フォールバック動作の実装方法に違いがあります。
clipboard-copy と copy-to-clipboard は、navigator.clipboard が利用可能であればそれを使用し、そうでなければ一時的な <textarea> を作成して select() + execCommand('copy') を実行します。これはセキュリティ上安全ですが、古いブラウザではユーザーに警告が表示される可能性があります。
ngclipboard, react-copy-to-clipboard, vue-clipboard2 はそれぞれのフレームワークのイベントシステム内から呼び出されるため、ユーザー操作のコンテキストが保たれやすく、権限エラーが発生しにくい設計になっています。
コピー操作は本質的に非同期ですが、各ライブラリのハンドリング方法は異なります。
clipboard-copy: Promiseを返すため、async/await で自然に扱えます。copy-to-clipboard: 同期的にbooleanを返しますが、内部で非同期APIを使用する場合でも即座に結果を返すため、実際のコピー完了を正確に検知できません。react-copy-to-clipboard: onCopy コールバックで結果を通知しますが、これは内部の copy-to-clipboard の戻り値に基づくため、Promiseのような正確な非同期制御はできません。ngclipboard と vue-clipboard2: イベント駆動で成功/失敗を通知しますが、非同期の詳細は隠蔽されています。正確な非同期制御が必要な場合は、clipboard-copy が最も適しています。
ngclipboard: Angular公式のCDK Clipboardが存在するため、新規プロジェクトではそちらを使用すべきです。ngclipboard はメンテナンスが活発でない可能性があります。vue-clipboard2: Vue 3非対応であり、Vue 2のサポート終了に伴い将来的に使用できなくなる可能性があります。Vue 3では @vueuse/core を推奨します。| プロジェクトタイプ | 推奨パッケージ | 理由 |
|---|---|---|
| Vanilla JS / Svelte / その他軽量フレームワーク | clipboard-copy | 軽量、Promise対応、依存関係ゼロ |
| 大規模なReactアプリ | copy-to-clipboard(直接使用) | Reactラッパー不要、細かい制御が可能 |
| 小規模なReactアプリ | react-copy-to-clipboard | 宣言的で簡単な統合 |
| Angularアプリ | @angular/cdk/clipboard | 公式サポート、最新のベストプラクティス |
| Vue 2アプリ | vue-clipboard2(一時的) | 既存コードとの互換性維持 |
| Vue 3アプリ | @vueuse/core | Composition API対応、アクティブなメンテナンス |
クリップボード操作は一見単純に見えますが、ブラウザのセキュリティモデルや非同期処理の扱いによって意外と複雑です。ライブラリを選ぶ際は、以下の点を確認してください:
clipboard-copy が最適です。clipboard-copy か copy-to-clipboard を選びましょう。これらのポイントを踏まえて、プロジェクトの要件に最も合うライブラリを選んでください。
copy-to-clipboard は同様にフレームワーク非依存ですが、より洗練されたAPIとPromiseベースのインターフェースを提供します。非同期処理を明示的に扱いたい場合や、コピー成功/失敗の結果をハンドリングしたいプロジェクトに向いています。また、オプションでフォールバック動作をカスタマイズできる柔軟性があり、中規模以上のアプリケーションで信頼性を重視する際に選ぶべきです。
react-copy-to-clipboard はReactコンポーネントとして提供され、children と text プロパティを受け取るシンプルなAPIを持ちます。Reactの宣言的UIモデルに自然にフィットし、状態管理なしでコピー機能を実装できます。ただし、内部で copy-to-clipboard を利用しているため、React以外の環境では不要な抽象レイヤーとなります。Reactプロジェクトで迅速に実装したい場合に適しています。
clipboard-copy は軽量で依存関係のない純粋なJavaScriptモジュールであり、フレームワークに依存しないシンプルなユースケースに最適です。特に、Vanilla JSプロジェクトや、最小限のバンドルサイズを求める静的サイトで推奨されます。内部で navigator.clipboard を優先し、古いブラウザではフォールバックとして一時的な <textarea> 要素を使用するため、広範なブラウザサポートを実現しています。
vue-clipboard2 はVue 2向けに設計されたプラグインであり、v-clipboard ディレクティブを通じてテンプレートに統合されます。Vue 2プロジェクトで簡潔にコピー機能を追加したい場合に便利ですが、Vue 3には非対応です。Vue 3を使用している場合は、代わりに @vueuse/core の useClipboard など、Composition API対応の代替手段を検討すべきです。
ngclipboard はAngular専用のディレクティブとして設計されており、テンプレート駆動の開発スタイルに完全に統合されます。Angularプロジェクトでボタンクリックなどのイベントから直接コピー機能を実装したい場合に最適です。ただし、公式のAngular CDK(Clipboardクラス)が存在するため、新規プロジェクトではそちらを検討すべきであり、このパッケージは既存のAngularアプリで後方互換性が必要な場合に限定して使用すべきです。
Simple module exposing copy function that will try to use execCommand with fallback to IE-specific clipboardData interface and finally, resort to usual prompt with proper text content and message.
import copy from 'copy-to-clipboard';
copy('Text');
// Copy with options
copy('Text', {
debug: true,
message: 'Press #{key} to copy',
});
copy(text: string, options: object): boolean — tries to copy text to clipboard. Returns true if no additional keystrokes were required from user (so, execCommand, IE's clipboardData worked) or false.
| Value | Default | Notes |
|---|---|---|
| options.debug | false | Boolean. Optional. Enable output to console. |
| options.message | Copy to clipboard: #{key}, Enter | String. Optional. Prompt message. * |
| options.format | "text/html" | String. Optional. Set the MIME type of what you want to copy as. Use text/html to copy as HTML, text/plain to avoid inherited styles showing when pasted into rich text editor. |
| options.onCopy | null | function onCopy(clipboardData: object): void. Optional. Receives the clipboardData element for adding custom behavior such as additional formats |
* all occurrences of #{key} are replaced with ⌘+C for macOS/iOS users, and Ctrl+C otherwise.
Works everywhere where prompt* is available. Works best (i.e. without additional keystrokes) in Chrome, FF, Safari 10+, and, supposedly, IE/Edge.
Note: does not work on some older iOS devices.
* – even though Safari 8 has prompt, you cannot specify prefilled content for prompt modal – thus it doesn't work as expected.
npm i --save copy-to-clipboard
<script src="https://wzrd.in/standalone/copy-to-clipboard@latest" async></script>
You will have window.copyToClipboard exposed for you to use.
This project has some automated tests, that will run using nightwatch on top of selenium.
npm i
npm test
This library has built-in Typescript definitions.
import * as copy from 'copy-to-clipboard';