clipboard、clipboard-polyfill、copy-to-clipboard、react-copy-to-clipboard、vue-clipboard2 はすべて、Web アプリケーションからユーザーのシステムクリップボードにテキストをコピーする機能を提供する npm パッケージです。これらのライブラリは、document.execCommand('copy') のような古い API や、現代の navigator.clipboard.writeText() Web API をラップまたはポリフィルすることで、クロスブラウザで安全かつ信頼性の高いコピー動作を実現します。各パッケージは異なる設計哲学と統合戦略を持っており、特にフレームワーク依存性(React/Vue 向け vs フレームワーク非依存)、ポリフィルの必要性、API の使いやすさにおいて差異があります。
Web アプリで「コピー」ボタンを実装するのは一見簡単ですが、実際にはブラウザのセキュリティ制限、API の進化、フレームワークとの統合など、多くの技術的課題があります。この記事では、代表的な5つの npm パッケージを、実際のコードと開発シナリオに基づいて深く比較します。
まず、最も単純なケース —— 任意の文字列をプログラムでコピーする —— で各ライブラリの使い勝手を確認します。
clipboard は DOM 要素に依存するため、直接文字列を渡せません。代わりに、data-clipboard-text 属性を持つ要素が必要です。
// clipboard: DOM 要素必須
import Clipboard from 'clipboard';
const btn = document.createElement('button');
btn.setAttribute('data-clipboard-text', 'Hello, world!');
document.body.appendChild(btn);
new Clipboard(btn);
// ボタンクリックでコピーされる(プログラムによる即時コピー不可)
clipboard-polyfill は Promise ベースのシンプルな関数呼び出しで動作します。
// clipboard-polyfill
import { writeText } from 'clipboard-polyfill';
writeText('Hello, world!').catch(err => console.error(err));
copy-to-clipboard も同様に、関数1つでコピー可能です。
// copy-to-clipboard
import copy from 'copy-to-clipboard';
copy('Hello, world!'); // boolean を返す(成功/失敗)
react-copy-to-clipboard は React コンポーネントとして使用します。
// react-copy-to-clipboard
import { CopyToClipboard } from 'react-copy-to-clipboard';
function App() {
return (
<CopyToClipboard text="Hello, world!">
<button>コピー</button>
</CopyToClipboard>
);
}
vue-clipboard2 は Vue ディレクティブでバインドします(Vue 2 限定)。
// vue-clipboard2 (Vue 2)
import Vue from 'vue';
import VueClipboard from 'vue-clipboard2';
Vue.use(VueClipboard);
// テンプレート内
// <button v-clipboard:copy="'Hello, world!'">コピー</button>
💡 ポイント:
clipboard以外は、DOM 要素を介さずに直接文字列をコピーできます。ただし、react-copy-to-clipboardとvue-clipboard2はそれぞれのフレームワークに強く依存しています。
現代のブラウザでは、navigator.clipboard.writeText() が標準ですが、これは HTTPS または localhost でのみ動作します。一方、古い document.execCommand('copy') は任意のコンテキストで動作しますが、非推奨です。
clipboard は execCommand のみ を使用します。そのため、最新ブラウザでも非推奨 API に依存し続けます。
clipboard-polyfill は Clipboard API を優先し、サポートされていない環境では execCommand にフォールバックします。さらに、iOS Safari の特殊な挙動にも対応しています。
copy-to-clipboard も同様に、モダン API を優先し、必要に応じて execCommand にフォールバックします。
react-copy-to-clipboard は内部で copy-to-clipboard を使用しているため、同じ互換性戦略を持ちます。
vue-clipboard2 は clipboard ライブラリに依存しており、execCommand のみ を使用します。
⚠️ 注意:
clipboardとvue-clipboard2は非推奨 API に依存しているため、新しいプロジェクトでは避けるべきです。特に、モバイル Safari や今後のブラウザアップデートで動作しなくなるリスクがあります。
コピー操作は常に成功するとは限りません(例: ユーザーが権限を拒否した場合)。各ライブラリのエラー処理方法を比較します。
clipboard-polyfill は Promise を返すため、catch でエラーを捕捉できます。
writeText('text').catch(err => {
console.error('コピー失敗:', err.message);
});
copy-to-clipboard は成功時に true、失敗時に false を返します。
const success = copy('text');
if (!success) {
console.warn('コピーに失敗しました');
}
clipboard と vue-clipboard2 はイベントリスナー経由で結果を取得します。
const clipboard = new Clipboard(btn);
clipboard.on('error', e => console.error('コピー失敗'));
react-copy-to-clipboard は onCopy コールバックで結果を通知します。
<CopyToClipboard text="text" onCopy={(text, result) => {
if (!result) console.warn('コピー失敗');
}}>
<button>コピー</button>
</CopyToClipboard>
💡 実践的アドバイス: Promise ベースの
clipboard-polyfillは非同期処理との統合が容易で、モダンなコードベースに適しています。一方、copy-to-clipboardの boolean 返り値はシンプルで直感的です。
react-copy-to-clipboard は JSX に自然に組み込めますが、カスタムロジック(例: 成功時のトースト表示)を追加するには onCopy を使う必要があります。copy-to-clipboard を直接使うと、より柔軟な制御が可能です。// copy-to-clipboard を React で使う例
import { useState } from 'react';
import copy from 'copy-to-clipboard';
function CopyButton({ text }) {
const [copied, setCopied] = useState(false);
const handleClick = () => {
if (copy(text)) {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
};
return <button onClick={handleClick}>{copied ? 'コピー済み' : 'コピー'}</button>;
}
vue-clipboard2 は Vue 2 専用であり、Vue 3 では動作しません。Vue 3 プロジェクトでは、copy-to-clipboard を Composition API でラップするのが現実的です。// Vue 3 + copy-to-clipboard の例
import { ref } from 'vue';
import copy from 'copy-to-clipboard';
export function useClipboard() {
const copied = ref(false);
const copyText = (text) => {
if (copy(text)) {
copied.value = true;
setTimeout(() => copied.value = false, 2000);
}
};
return { copied, copyText };
}
公式情報によると:
clipboard は GitHub リポジトリで「このプロジェクトはメンテナンスされていません」と明記されており、新しいプロジェクトでの使用は推奨されません。vue-clipboard2 は Vue 3 に対応しておらず、最終更新が古いため、Vue 2 レガシープロジェクト以外では避けるべきです。一方、clipboard-polyfill と copy-to-clipboard は積極的にメンテナンスされており、最新のブラウザ変更にも追随しています。
| ライブラリ | 推奨用途 | フレームワーク依存 | モダン API 対応 | 新規プロジェクト向け |
|---|---|---|---|---|
clipboard | レガシーな静的サイト | なし | ❌ | ❌ |
clipboard-polyfill | クロスブラウザ対応が必要な汎用アプリ | なし | ✅(ポリフィル付き) | ✅ |
copy-to-clipboard | シンプルで軽量なコピー機能 | なし | ✅(自動フォールバック) | ✅ |
react-copy-to-clipboard | React 専用の簡易実装 | React | ✅(内部で copy-to-clipboard 使用) | △(小規模向け) |
vue-clipboard2 | Vue 2 レガシープロジェクト | Vue 2 | ❌ | ❌ |
clipboard-polyfill(完全なポリフィル)または copy-to-clipboard(軽量)react-copy-to-clipboard(ただし、カスタムロジックが必要なら copy-to-clipboard 直接使用が柔軟)copy-to-clipboard を Composition API でラップclipboard や vue-clipboard2 を使うのは避けてください。非推奨 API への依存は将来的な破壊的変更を招きます。クリップボード操作は「小さな機能」に見えますが、ユーザー体験に直結します。信頼性と将来性を考えて、適切なツールを選びましょう。
copy-to-clipboard はシンプルな関数ベースの API を持ち、任意の文字列をコピーするための最小限のユーティリティです。React や Vue などのフレームワークに依存せず、軽量で直感的に使用できます。モダンブラウザでは Clipboard API を、古い環境では execCommand を内部で自動的に切り替えて使用するため、バランスの取れた選択肢です。複雑な DOM 操作やトリガー要素不要なケースに最適です。
clipboard は DOM 要素に直接バインドして動作する軽量なライブラリです。ボタンクリックなどのイベント発火時に特定の要素の内容や属性値をコピーしたい場合に最適です。ただし、execCommand に依存しており、モダンな Clipboard API には対応していません。新しいプロジェクトでは、セキュリティ制限や非推奨化のリスクを考慮し、代替手段を検討すべきです。
react-copy-to-clipboard は React 専用のコンポーネントとして設計されており、JSX 内で宣言的にコピー機能を実装できます。<CopyToClipboard> コンポーネントに text プロパティを渡すだけで、子要素のクリックでコピーが発火します。React プロジェクトで迅速にコピー UI を実装したい場合に便利ですが、React 以外の環境では使用できません。内部では copy-to-clipboard パッケージを利用しています。
clipboard-polyfill は navigator.clipboard.writeText() の完全なポリフィルを提供し、古いブラウザでも動作するように設計されています。フレームワークに依存せず、純粋な JavaScript 環境で一貫した API を使いたい場合に最適です。特に、セキュリティコンテキスト(HTTPS や localhost)外でも動作させる必要があるレガシー環境向けに有用ですが、最新ブラウザのみをターゲットにする場合はオーバーヘッドになる可能性があります。
vue-clipboard2 は Vue 2 向けのディレクティブ (v-clipboard) を提供し、Vue コンポーネント内で簡単にクリップボード機能をバインドできます。Vue 2 プロジェクトで既存のボタンや要素にコピー動作を追加したい場合に最適です。ただし、Vue 3 には正式に対応しておらず、メンテナンス状況を確認する必要があります。新しい Vue プロジェクトでは、代わりに @vueuse/core の useClipboard などを検討すべきです。
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';