web-dev-qa-db-fra.com

Comment copier des fichiers statiques pour construire un répertoire avec Webpack?

J'essaie de passer de Gulp à Webpack. Dans Gulp j’ai une tâche qui copie tous les fichiers et dossiers du dossier / static / dans le dossier / build /. Comment faire la même chose avec Webpack? Ai-je besoin d'un plugin?

290
Vitalii Korsakov

Vous n'avez pas besoin de copier les choses, Webpack fonctionne différemment de gulp. Webpack est un bundle de modules et tout ce que vous référencez dans vos fichiers sera inclus. Il vous suffit de spécifier un chargeur pour cela.

Donc si vous écrivez:

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

Webpack essaiera d’abord d’analyser le fichier référencé au format JavaScript (car c’est la valeur par défaut). Bien sûr, cela va échouer. C'est pourquoi vous devez spécifier un chargeur pour ce type de fichier. Le fichier - ou rl-loader , par exemple, prend le fichier référencé, le place dans le dossier de sortie de Webpack (qui devrait être build dans votre cas) et renvoie le URL hachée pour ce fichier.

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

Habituellement, les chargeurs sont appliqués via la configuration webpack:

// webpack.config.js

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

Bien sûr, vous devez d'abord installer le chargeur de fichiers pour que cela fonctionne.

173
Johannes Ewald

Exiger des ressources à l'aide du module chargeur de fichiers est la façon dont le pack Web doit être utilisé ( source ). Toutefois, si vous avez besoin d'une plus grande flexibilité ou si vous souhaitez une interface plus propre, vous pouvez également copier des fichiers statiques directement à l'aide de mon copy-webpack-plugin ( npm , Github ). Pour votre exemple static à build:

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

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

Si vous souhaitez copier vos fichiers statiques, vous pouvez utiliser le chargeur de fichiers de cette manière:

pour les fichiers html:

dans webpack.config.js:

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

dans votre fichier js:

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

./static/ est relatif à l’emplacement de votre fichier js.

Vous pouvez faire la même chose avec des images ou autre chose. Le contexte est une méthode puissante à explorer!

53
Moussa Dembélé

Un des avantages apportés par le copy-webpack-plugin susmentionné et qui n'a pas été expliqué auparavant est que toutes les autres méthodes mentionnées ici regroupent toujours les ressources dans vos fichiers bundle (et vous obligent à "exiger" ou "importer" quelque part). Si je veux simplement déplacer des images ou des modèles partiels, je ne veux pas encombrer mon fichier de paquet javascript avec des références inutiles, je veux juste que les fichiers soient émis au bon endroit. Je n'ai pas trouvé d'autre moyen de faire cela dans Webpack. Certes, ce n'est pas pour quoi le webpack a été conçu à l'origine, mais il s'agit sans aucun doute d'un cas d'utilisation courant. (@BreakDS j'espère que cela répond à votre question - ce n'est qu'un avantage si vous le voulez)

10
steev

Les suggestions ci-dessus sont bonnes. Mais pour essayer de répondre directement à votre question, je suggérerais d'utiliser cpy-cli dans un script défini dans votre package.json.

Cet exemple attend de node quelque part sur votre chemin. Installez cpy-cli en tant que dépendance de développement:

npm install --save-dev cpy-cli

Ensuite, créez quelques fichiers nodejs. Un pour faire la copie et l'autre pour afficher une coche et un message.

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;

Ajoutez le script dans package.json. En supposant que les scripts sont dans <project-root>/scripts/

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

Pour exécuter le script:

npm run copy

7
RnR

Très probablement, vous devriez utiliser CopyWebpackPlugin qui a été mentionné dans la réponse kevlened. Alternativement pour certains types de fichiers tels que . Html ou . Json vous pouvez également utiliser raw-loader ou json-loader. Installez-le via npm install -D raw-loader et vous n'aurez plus qu'à ajouter un autre chargeur à notre fichier webpack.config.js.

Comme:

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

Remarque: Redémarrez webpack-dev-server pour que les modifications de configuration prennent effet.

Et maintenant, vous pouvez exiger des fichiers HTML en utilisant des chemins relatifs, cela facilite beaucoup le déplacement des dossiers.

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

La façon dont je charge statique images et fonts:

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/'
          },
        }
    ]
}

N'oubliez pas d'installer file-loader pour que cela fonctionne.

4
RegarBoy

Le fichier de configuration webpack (dans webpack 2) vous permet d'exporter une chaîne de promesse, à condition que la dernière étape renvoie un objet de configuration webpack. Voir les documents de configuration de promesse . De là:

webpack prend désormais en charge le retour d'une promesse à partir du fichier de configuration. Cela permet de faire un traitement asynchrone dans votre fichier de configuration.

Vous pouvez créer une fonction de copie récursive simple qui copie votre fichier, et uniquement après que cela déclenche webpack. Par exemple.:

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

J'étais coincé ici aussi. copy-webpack-plugin a fonctionné pour moi.

Cependant, 'copie-webpack-plugin' n'était pas nécessaire dans mon cas (j'ai appris plus tard).

webpack ignore les chemins racine
exemple

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

Par conséquent, pour que cela fonctionne sans utiliser 'copy-webpack-plugin', utilisez '~' dans les chemins

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

"~" indique à Webpack de considérer les "images" comme un module

remarque: vous devrez peut-être ajouter le répertoire parent du répertoire images dans

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

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

2
techNik

disons que tous vos actifs statiques sont dans un dossier "statique" au niveau de la racine et que vous voulez les copier dans le dossier de construction en conservant la structure du sous-dossier, puis dans votre fichier d'entrée)

//index.js or index.jsx

require.context("!!file?name=[path][name].[ext]&context=./static!../static/", true, /^\.\/.*\.*/);
1
abhisekpaul

Vous pouvez écrire bash dans votre package.json:

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