静的ファイルをWebpackでビルドディレクトリにコピーする方法は?


330

からに移動しようとしGulpていWebpackます。でGulp、私はそのコピーからすべてのファイルとフォルダのタスク持た/静的/フォルダへ/ビルド/フォルダを。同じようにするにはどうすればよいWebpackですか?プラグインは必要ですか?


2
Gulpは理解に優れています。必要に応じてgulpfile.jsからwebpackを呼び出すだけ
Baryon Lee

Laravel Mixを使用している場合は、laravel.com / docs / 5.8 / mix #copying-files-and-directoriesを利用できます。
ライアン

回答:


179

Webpackの動作はgulpとは異なります。Webpackはモジュールバンドルであり、ファイルで参照するすべてのものが含まれます。そのためのローダーを指定するだけです。

だからあなたが書くなら:

var myImage = require("./static/myImage.jpg");

Webpackは最初に参照ファイルをJavaScriptとして解析しようとします(これがデフォルトであるため)。もちろん、それは失敗します。そのため、そのファイルタイプのローダーを指定する必要があります。ファイル -またはURLローダインスタンスのためには、参照先のファイルを取る(あるべきのWebPACKの出力フォルダに入れてbuild、あなたのケースで)と、そのファイルのハッシュされたURLを返します。

var myImage = require("./static/myImage.jpg");
console.log(myImage); // '/build/12as7f9asfasgasg.jpg'

通常、ローダーはwebpack設定を介して適用されます:

// webpack.config.js

module.exports = {
    ...
    module: {
        loaders: [
            { test: /\.(jpe?g|gif|png|svg|woff|ttf|wav|mp3)$/, loader: "file" }
        ]
    }
};

もちろん、これを機能させるには、最初にファイルローダーをインストールする必要があります。


42
もちろん、これを機能させるためには、最初にファイルローダーをインストールする必要があります。」前述の「ファイルローダー」へのリンクはこちら。そして、ここにそれをインストールして使用する方法があります。
2015

21
あなたはまだHTMLファイルとロードされていないそれらのすべての参照の問題を抱えています。
kilianc

126
ええ、もしあなたがWebpackプラグインの地獄に行きたければ、あなたはファイルローダー、CSSローダー、スタイルローダー、URLローダーを使うことができます...そしてあなたはそれをあなたが必要とするように構成する素晴らしい時間を持つことができますそしてグーグルで眠らない:)または、copy-webpack-pluginを使用して仕事を完了することができます...
KamilTomšík16年

11
@KamilTomšíkでは、webpackプラグインを回避するためにwebpackプラグインを使用することをお勧めしますか?(冗談です。私はあなたのポイントを得ました。)
Konrad Viltersten

12
わかりました、すべての画像の大部分はcssとhtmlです。したがって、require( 'img.png');を使用して、JSファイルでこれらのすべての画像を要求する必要があります。そのファイルローダーで動作させるには?それはかなりおかしなことです。
ランティエフ2017

581

ファイルローダーモジュールを使用してアセットを要求することは、webpackの使用方法(ソース)です。ただし、より高い柔軟性が必要な場合や、よりクリーンなインターフェイスが必要な場合は、my copy-webpack-pluginnpmGithub)を使用して静的ファイルを直接コピーすることもできます。あなたのためstaticbuild例:

const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    context: path.join(__dirname, 'your-app'),
    plugins: [
        new CopyWebpackPlugin([
            { from: 'static' }
        ])
    ]
};

11
これは、ディレクトリ全体(つまり、静的htmlやその他のボイラープレートイメージ)をコピーする場合に、はるかに簡単です。
Arjun Mehta

6
トリックをやりましたか、ありがとうございます:)非常に単純なコマンドを実行するために数回失敗した後、ファイルローダーをあきらめました。プラグインは初めて動作しました。
arcseldon

3
@Yanプラグインは、ファイルが変更された場合にファイルを再コピーします(dev-serverまたはwebpack --watch)。コピーされない場合は、問題を報告してください。
16

2
Webpackは初めてですが、単にコピーするのではなく、file-loader / url-loader / img-loaderを使用する必要がある理由を理解するのに苦労していますか?ファイルローダーなどでこれを行うことで得られるメリットは何ですか?
BreakDS 2017年

2
あなたはプラグインの作者なので。この質問をするためのより良いペースはありません。「copy-webpack-plugin」プラグインを使用して...ソースディレクトリからファイルをフィルタリングして、特定のファイル拡張子exを含むファイルのみをコピーすることができますか。「.html」のみをコピーしますか?よろしく
DevWL

56

静的ファイルをコピーする場合は、次のようにファイルローダーを使用できます。

htmlファイルの場合:

webpack.config.js内:

module.exports = {
    ...
    module: {
        loaders: [
            { test: /\.(html)$/,
              loader: "file?name=[path][name].[ext]&context=./app/static"
            }
        ]
    }
};

あなたのjsファイルで:

  require.context("./static/", true, /^\.\/.*\.html/);

./static/は、jsファイルの場所を基準にしています。

画像でも何でも同じことができます。コンテキストは探索する強力な方法です!!


3
私はcopy-webpack-pluginモジュールよりもこの方法を好みます。さらに、Webパック構成で「&context =。/ app / static」を使用せずに機能させることができました。require.context行だけが必要でした。
Dave Landry 2016年

2
私はこれをしようとしている、それは素晴らしいようだが、それは私を入れているということである私が取得しています一つの小さな問題、のためにindex.html呼ばれ、それが作成されるサブディレクトリに_(アンダースコア)、何が起こっているの?
クリス2016

2
「jsファイルで」と言うとき、どういう意味ですか?JSファイルがない場合はどうなりますか?
evolutionxbox

絶対に。この1行のエントリスクリプトで、つまりは、main.js内のすべてのインポートされstaticたフォルダ:require.context("./static/", true, /^.*/);
マリオ

2
これはきちんとしたハックですが、コピーするファイルが多すぎると、メモリが不足します。
トム

18

前述のcopy-webpack-pluginがもたらす利点の1つは、これまでに説明されていないことですが、ここで説明する他のすべての方法では、リソースをバンドルファイルにバンドルします(また、どこかにリソースを「要求」または「インポート」する必要があります)。一部の画像やテンプレートの部分テンプレートを移動するだけの場合は、JavaScriptバンドルファイルを不要な参照で乱雑にしたくないので、ファイルを適切な場所に出力します。これをwebpackで行う他の方法は見つかりませんでした。確かに、それは本来webpackが設計されたものではありませんが、間違いなく現在のユースケースです。(@BreakDSこれがあなたの質問に答えることを願っています-あなたがそれを望むならそれだけが利益です)


7

上記の提案は良いです。しかし、あなたの質問に直接答えようとするためにcpy-cli、あなたので定義されたスクリプトで使用することをお勧めしますpackage.json

この例ではnode、パスのどこかに期待しています。cpy-cli開発依存関係としてインストールします。

npm install --save-dev cpy-cli

次に、いくつかのnodejsファイルを作成します。1つはコピーを行い、もう1つはチェックマークとメッセージを表示します。

copy.js

#!/usr/bin/env node

var shelljs = require('shelljs');
var addCheckMark = require('./helpers/checkmark');
var path = require('path');

var cpy = path.join(__dirname, '../node_modules/cpy-cli/cli.js');

shelljs.exec(cpy + ' /static/* /build/', addCheckMark.bind(null, callback));

function callback() {
  process.stdout.write(' Copied /static/* to the /build/ directory\n\n');
}

checkmark.js

var chalk = require('chalk');

/**
 * Adds mark check symbol
 */
function addCheckMark(callback) {
  process.stdout.write(chalk.green(' ✓'));
  callback();
}

module.exports = addCheckMark;

にスクリプトを追加しますpackage.json。スクリプトがあると仮定<project-root>/scripts/

...
"scripts": {
  "copy": "node scripts/copy.js",
...

sriptを実行するには:

npm run copy


3
OPは、npmスクリプトを使用せずに、webpack内でファイルを移動したいですか?
ウィリアムS

OPは、この内部のWebPACKのを解決したい場合でも、彼がWebPACKのが実行された彼のビルドスクリプトに追加することができるように、彼はNPM経由のWebPACKを実行している可能です
Piroさんが復活モニカ言う

5

おそらくあなたはkevlened answerで言及されたCopyWebpackPluginを使うべきです。代わりに、.html.jsonなどのある種のファイルでは、raw-loaderまたはjson-loaderを使用することもできます。を介してインストールしてnpm install -D raw-loaderから、webpack.config.jsファイルに別のローダーを追加するだけです。

お気に入り:

{
    test: /\.html/,
    loader: 'raw'
}

注:構成の変更を有効にするには、webpack-dev-serverを再起動します。

そして、相対パスを使用してhtmlファイルを要求できるようになりました。これにより、フォルダの移動がはるかに簡単になります。

template: require('./nav.html')  

5

方法I荷重静的imagesfonts

module: {
    rules: [
      ....

      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        /* Exclude fonts while working with images, e.g. .svg can be both image or font. */
        exclude: path.resolve(__dirname, '../src/assets/fonts'),
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'images/'
          }
        }]
      },
      {
        test: /\.(woff(2)?|ttf|eot|svg|otf)(\?v=\d+\.\d+\.\d+)?$/,
        /* Exclude images while working with fonts, e.g. .svg can be both image or font. */
        exclude: path.resolve(__dirname, '../src/assets/images'),
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: 'fonts/'
          },
        }
    ]
}

file-loaderそれを機能させるためにインストールすることを忘れないでください。


重複するファイル名をどのように処理しますか?またはさらに良いことに、新しい出力ディレクトリに元のパスを保持する方法を知っていますか?
cantuket

プロジェクトで同じ拡張子名の重複したファイル名を使用しないでください。内容が同じである場合、重複を維持することのポイントは何ですか?そうでない場合は、内容に応じて異なる名前を付けます。ただし、元のパスを維持したいのに、なぜwebpackを使用するのでしょうか。JSの翻訳だけが必要な場合は、Babelで十分です。
RegarBoy

1
コンポーネントベースの開発を実装している場合(その主な原則の1つはカプセル化であり、より具体的にはこの場合は情報を非表示にすることです、あなたが言及した内容はどれも適切ではありません。つまり、誰かがプログラムに新しいコンポーネントを追加するとき、別の名前のイメージがあるかどうかを確認したり、logo.pngグローバルな衝突を避けるために鈍くて「うまくいけば」一意のファイル名を作成したりする必要はありません。CSSモジュールを使用するのと同じ理由。
cantuket

1
なぜ画像に元のパスとファイル名を維持させたいのか。ほとんどの場合、ソースマップを使用するのと同じ理由で、SEOもデバッグします。とにかく、私の質問への答えは実際には非常に単純でした... [path][name].[ext]そして、特定の環境またはユースケースに合わせてこれを変更するために提供された多くの柔軟性があります... file-loader
cantuket

1
そうは言っても、私たちはあなたの例のバリエーションを実装したので、提供してくれてありがとう!
cantuket

3

あなたはpackage.jsonにbashを書くことができます:

# package.json
{
  "name": ...,
  "version": ...,
  "scripts": {
    "build": "NODE_ENV=production npm run webpack && cp -v <this> <that> && echo ok",
    ...
  }
}

1
Windowsでは、単にCPの代わりにxcopyを使用します"build": "webpack && xcopy images dist\\images\\ /S /Y && xcopy css dist\\css\\ /S /Y"
SebaGra

7
そうですね、ソリューションはOSごとに異なるスクリプトを持つことですか?
Maciej Gurban 2017年

はい、私にとっては各OSのスクリプトは許容されます(LinuxのスクリプトはDarwinまたは別のPOSIX * nixで実行されるため、実際にはunix / non-unixです)
Victor Pudeyev

また、そのWindowsの例は、PowerShellを既定のシェルとして使用することもできません。
ジュリアンナイト

CopyWebpackPluginとは異なり、このオプションはファイルの日付を保持します。OSの問題はオープンソースでは問題になる可能性がありますが、小規模なチームではWindows bashまたはxcopyをcp.batでラップすることで簡単に管理できます。
Alien Technology、

2

私もここで行き詰まりました。copy-webpack-pluginがうまくいきました。

ただし、私の場合は「copy-webpack-plugin」は必要ありませんでした(後で学習しました)。

webpackがルートパスを無視する

<img src="/images/logo.png'>

したがって、「copy-webpack-plugin」を使用せずにこれを機能させるには、パスで「〜」を使用します

<img src="~images/logo.png'>

'〜'は 'packets'をモジュールと見なすようにwebpackに指示します

注:画像ディレクトリの親ディレクトリを

resolve: {
    modules: [
        'parent-directory of images',
        'node_modules'
    ]
}

訪問https://vuejs-templates.github.io/webpack/static.html


2

(webpack 2の)webpack構成ファイルを使用すると、最後のステップでwebpack構成オブジェクトが返される限り、promiseチェーンをエクスポートできます。promise configuration docsを参照してください。そこから:

webpackが設定ファイルからPromiseを返すことをサポートするようになりました。これにより、構成ファイルで非同期処理を実行できます。

ファイルをコピーする単純な再帰的コピー関数を作成し、その後にのみwebpackをトリガーすることができます。例えば:

module.exports = function(){
    return copyTheFiles( inpath, outpath).then( result => {
        return { entry: "..." } // Etc etc
    } )
}

1

すべての静的アセットがルートレベルの「静的」フォルダーにあり、サブフォルダーの構造を維持してビルドフォルダーにコピーして、エントリーファイルにコピーする場合は、

//index.js or index.jsx

require.context("!!file?name=[path][name].[ext]&context=./static!../static/", true, /^\.\/.*\.*/);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.