Webpack.config como apenas copiar o index.html para a pasta dist

189

Estou tentando automatizar ativos que entram em / dist. Eu tenho o seguinte config.js:

module.exports = {
  context: __dirname + "/lib",
  entry: {
    main: [
      "./baa.ts"
    ]
  },
  output: {
    path: __dirname + "/dist",
    filename: "foo.js"
  },
  devtool: "source-map",
  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'awesome-typescript-loader'
      },
      { test: /\.css$/, loader: "style-loader!css-loader" }
    ]
  },
  resolve: {
    // you can now require('file') instead of require('file.js')
    extensions: ['', '.js', '.json']
  }
}

Também quero incluir main.html do diretório que fica ao lado de / lib, na pasta / dist ao executar o webpack. Como posso fazer isso?

ATUALIZAÇÃO 1 2017_____________

Minha maneira favorita de fazer isso agora é usar o html-webpack-pluginarquivo com um modelo. Graças à resposta aceita também! A vantagem dessa maneira é que o arquivo de índice também terá o link js armazenado em cache adicionado da caixa!

SuperUberDuper
fonte

Respostas:

162

Opção 1

No seu index.jsarquivo (por exemplo, entrada do webpack), adicione um requerimento ao seu plugin index.htmlvia carregador de arquivo , por exemplo:

require('file-loader?name=[name].[ext]!../index.html');

Depois de criar seu projeto com o webpack, index.html ele estará na pasta de saída.

opção 2

Use o html-webpack-plugin para evitar o index.html. Basta fazer com que o webpack gere o arquivo para você.

VitalyB
fonte
2
posso de alguma forma carregá-lo escrevendo algo no próprio arquivo de configuração?
codeVerine
Tentei da primeira maneira e copiou os arquivos. Mas o CSS que eu estava copiando parou de funcionar corretamente. (Eu precisava externo para Webpack porque Handsontable pode não funcionar com Webpack.)
Vaccano
@ Vulcano for CSS, você não deve usar esse método. Use um estilo-loader e css-loader, consulte aqui: stackoverflow.com/questions/34039826/...
VitalyB
4
No webpack v2, você aparentemente não pode omitir o -loadersufixo. por exemplorequire('file-loader?name=[name].[ext]!../index.html');
overthink
1
@codeVerine Sim, usando adicionando algo como { test: /index\.html/, loader: 'file-loader', query: { name: '[name].[ext]' }a sua loadersmatriz no seu arquivo de configuração do webpack, só não consegui que o webpack-dev-server o servisse, levando a, curiosamente, um 404 ao solicitar /(a raiz não existe !).
Brian McCutchon
67

Vou adicionar uma opção à resposta do VitalyB:

Opção 3

Via npm. Se você executar seus comandos via npm, poderá adicionar esta configuração ao seu package.json (consulte também o webpack.config.js também). Para o desenvolvimento da execução npm start, não é necessário copiar o index.html nesse caso, porque o servidor da Web será executado no diretório de arquivos de origem e o bundle.js estará disponível no mesmo local (o bundle.js permanecerá apenas na memória, mas estará disponível como se estivesse localizado junto com index.html). Para execução da produção, npm run builduma pasta dist conterá seu bundle.js e o index.html será copiado com o bom e velho comando cp, como você pode ver abaixo:

"scripts": {
    "test": "NODE_ENV=test karma start",
    "start": "node node_modules/.bin/webpack-dev-server --content-base app",
    "build": "NODE_ENV=production node node_modules/.bin/webpack && cp app/index.html dist/index.html"
  }

Atualização: opção 4

Existe um copy-webpack-plugin , conforme descrito nesta resposta do Stackoverflow

Mas, geralmente, exceto pelo "primeiro" arquivo (como index.html) e pelos recursos maiores (como imagens grandes ou vídeo), inclua o css, html, imagens etc. diretamente no seu aplicativo via via requirewebpack e o incluirá para você (bem, depois de configurá-lo corretamente com carregadores e possivelmente plugins).

EricC
fonte
11
A opção 3 deve ser a opção 1
Gil Epshtain
2
Tentei a opção 3, mas o recarregamento a quente de index.html não funcionou. Você não edita seu index.html com muita frequência? Pergunta séria.
stone
3
Use ncp em vez de cp se desejar oferecer suporte a ambientes de desenvolvimento entre sistemas operacionais
Vivek Maharajh
32

Você poderia usar o CopyWebpackPlugin . Está funcionando assim:

module.exports = {
  plugins: [
    new CopyWebpackPlugin([{
      from: './*.html'
    }])
  ]
}
hobbeshunter
fonte
Agora que o Webpack substituiu o Gulp e o Grunt, não apenas fazendo empacotamento, mas também muitas outras tarefas relacionadas à compilação, esta solução é o que eu vi na maioria dos projetos. Os scripts in package.jsonsão usados ​​apenas para coisas simples, como iniciar o test runner ou o servidor de desenvolvimento.
Robert Jack Will
15

Eu diria que a resposta é: você não pode. (ou pelo menos: você não deveria). Não é isso que o Webpack deve fazer. O Webpack é um empacotador e não deve ser usado para outras tarefas (neste caso: copiar arquivos estáticos é outra tarefa). Você deve usar uma ferramenta como Grunt ou Gulp para executar essas tarefas. É muito comum integrar o Webpack como uma tarefa Grunt ou como uma tarefa Gulp . Ambos têm outras tarefas úteis para copiar arquivos como você descreveu, por exemplo, grunt-contrib-copy ou gulp-copy .

Para outros ativos (não os index.html), você pode apenas agrupá-los com o Webpack (é exatamente para isso que serve o Webpack). Por exemplo var image = require('assets/my_image.png');,. Mas suponho que suas index.htmlnecessidades não façam parte do pacote configurável e, portanto, não é um trabalho para o pacote configurável.

Brodie Garnet
fonte
59
Fui precisamente ao webpack para não precisar grunhir ou engolir. Existe alguma outra alternativa? Se eu precisar usar gulp, por que devo me preocupar com o webpack?
SuperUberDuper
4
A questão está de cabeça para baixo. Por que você deve usar o webpack se pode usar grunhido ou gole? Eles são muito bons sistemas de tarefas / construção. O Webpack (ou browserify ou r.js) são ferramentas que você pode usar para agrupar muitos arquivos JS (e outros recursos) em um grande (ou múltiplo) pacote javascript. Você deve usar a ferramenta correta para o trabalho. E, novamente, é muito comum executar o webpack, o browserify ou outros bundlers do grunhido ou gulp.
Brodie Garnet
1
Existem várias maneiras de o webpack fazer isso. Você poderia usar file-loadero que basicamente apenas copia o arquivo / imagem no diretório de saída e dá-lhe a url quando você exige: var url = require('myFile');. Como eu disse, um pacote pode ser um ou vários arquivos.
Brodie Garnet
1
Eu poderia usar brocolli como o processo de criação dos pais
SuperUberDuper
1
Esta é a resposta certa para mim. Em projetos grandes / complexos, o desempenho da compilação do webpack é uma consideração importante. Vários plug-ins de cópia de arquivo adicionam custos desnecessários ao webpack, permitindo que o webpack se concentre no pacote JS é uma idéia melhor.
Evi Song
14

Você pode adicionar o índice diretamente à sua configuração de entrada e usar um carregador de arquivos para carregá-lo

module.exports = {

  entry: [
    __dirname + "/index.html",
    .. other js files here
  ],

  module: {
    rules: [
      {
        test: /\.html/, 
        loader: 'file-loader?name=[name].[ext]', 
      },
      .. other loaders
    ]
  }

}
Jake Coxon
fonte
5

Para copiar um index.htmlarquivo já existente no distdiretório, você pode simplesmente usar o HtmlWebpackPlugin especificando a fonte index.htmlcomo um modelo .

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // ...
  plugins: [    
    new HtmlWebpackPlugin({
      template: './path/to/index.html',
    })
  ],
  // ...
};

O dist/index.htmlarquivo criado será basicamente o mesmo que o arquivo de origem, com a diferença de que recursos agrupados, como arquivos .js, são injetados com <script>tags pelo webpack. Minificação e outras opções podem ser configuradas e estão documentadas no github .

Tobi Obeck
fonte
3

Isso funciona bem no Windows:

  1. npm install --save-dev copyfiles
  2. Em package.jsoneu tenho uma tarefa de cópia:"copy": "copyfiles -u 1 ./app/index.html ./deploy"

Isso move meu index.html da pasta do aplicativo para a pasta de implantação.

Patrick Desjardins
fonte
Eu entendo funciona usando resposta lá: stackoverflow.com/questions/38858718/...
IsraGab
3

Para estender a resposta do @ hobbeshunter se você quiser usar apenas o index.html, você também pode usar o CopyPlugin. A principal motivação para usar esse método em detrimento de outros pacotes é porque é um pesadelo adicionar muitos pacotes para cada tipo e configurá-lo etc. A maneira mais fácil é usar o CopyPlugin para tudo:

npm install copy-webpack-plugin --save-dev

Então

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

module.exports = {
  plugins: [
    new CopyPlugin([
      { from: 'static', to: 'static' },
      { from: 'index.html', to: 'index.html', toType: 'file'},
    ]),
  ],
};

Como você pode ver, copie toda a pasta estática, juntamente com todo o seu conteúdo, para a pasta dist. Nenhum css ou arquivo ou qualquer outro plug-in necessário.

Embora esse método não sirva para tudo, ele faria o trabalho de maneira simples e rápida.

Remy
fonte
-1

Eu também achei fácil e genérico o suficiente para colocar meu index.html arquivo no dist/ diretório e adicionar <script src='main.js'></script>para index.htmlincluir meus arquivos Webpack empacotados. main.jsparece ser o nome de saída padrão do nosso pacote, se nenhum outro for especificado no arquivo conf do webpack . Acho que não é uma solução boa e de longo prazo, mas espero que ajude a entender como o webpack funciona.

Qback
fonte