Plusieurs fichiers HTML à l'aide de Webpack

87

J'essaye de faire quelque chose dans un projet dont je ne sais pas si c'est possible, je suis dans une mauvaise direction ou je ne comprends pas quelque chose. Nous utilisons webpack, et l'idée est de servir plus d'un fichier html.

localhost: 8181 -> sert index.html
localhost: 8181 / example.html -> sert example.html

J'essaie de le faire en définissant plusieurs points d'entrée, en suivant la documentation :

La structure des dossiers est:

/
|- package.json
|- webpack.config.js
  /src
   |- index.html
   |- example.html
   | /js
      |- main.js
      |- example.js

Webpack.config.js:

...
entry: {
    main: './js/main.js',
    exampleEntry: './js/example.js'
},
output: {
    path: path.resolve(__dirname, 'build', 'target'),
    publicPath: '/',
    filename: '[name].bundle.js',
    chunkFilename: '[id].bundle_[chunkhash].js',
    sourceMapFilename: '[file].map'
},
...

index.html

<!DOCTYPE html>
<html
<head>
    ...
    <link type="text/css" href="https://stackoverflow.com/style/default.css">
</head>
<body>
    <div id="container"></div>
    <script src="/main.bundle.js"></script>
</body>
</html>

example.html:

<!DOCTYPE html>
<html
<head>
    ...
    <link type="text/css" href="https://stackoverflow.com/style/default.css">
</head>
<body>
    ...
    <script src="/example.bundle.js"></script>
</body>
</html>

Quelqu'un sait ce que je fais de mal?

Merci.

miguelitomp
la source
Êtes-vous en mesure de trouver la solution pour cela? Je recherche également le même cas d'utilisation.
monica

Réponses:

118

Voir un point d'entrée comme la racine d'une arborescence qui fait référence à de nombreux autres actifs tels que des modules javascript, des images, des modèles, etc. Lorsque vous définissez plus d'un point d'entrée, vous divisez essentiellement vos actifs en soi-disant morceaux pour ne pas avoir tout votre code et vos actifs dans un seul ensemble.

Ce que je pense que vous voulez réaliser est d'avoir plus d'un "index.html" pour différentes applications qui font également référence à différents morceaux de vos actifs que vous avez déjà définis avec vos points d'entrée.

Copier un fichier index.html ou même en générer un avec des références à ces points d'entrée n'est pas géré par le mécanisme de point d'entrée - c'est l'inverse. Une approche de base pour la gestion des pages html consiste à utiliser le html-webpack-pluginqui non seulement peut copier des fichiers html, mais dispose également d'un mécanisme étendu de création de modèles. Ceci est particulièrement utile si vous souhaitez que vos bundles soient suffixés avec un hachage de bundle assez pratique pour éviter les problèmes de mise en cache du navigateur lorsque vous mettez à jour votre application.

Comme vous avez défini un modèle de nom comme [id].bundle_[chunkhash].js vous ne pouvez plus référencer votre bundle javascript main.bundle.jscar il s'appellera quelque chose comme main.bundle_73efb6da.js.

Jetez un œil à la plugin html-webpack-plugin . Particulièrement pertinent pour votre cas d'utilisation:

Vous devriez probablement avoir quelque chose comme ça à la fin (attention: non testé)

plugins: [
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: 'src/index.html',
    chunks: ['main']
  }),
  new HtmlWebpackPlugin({
    filename: 'example.html',
    template: 'src/example.html',
    chunks: ['exampleEntry']
  })
]

Veuillez noter que vous devez référencer le nom du point d'entrée dans le tableau des morceaux, donc dans votre exemple cela devrait être exampleEntry . C'est probablement aussi une bonne idée de déplacer vos modèles dans un dossier spécifique au lieu de les avoir directement dans le dossier racine src.

J'espère que cela t'aides.

Andreas Jägle
la source
4
Bonne explication, mais cela me dérange toujours que vous deviez appeler «nouveau HTMLWebPlugin» pour chaque page que vous créez dans votre projet.
klewis
Tout le monde n'aime pas appeler le «nouveau HTMLWebPlugin» chacune des pages. Besoin d'alternative.
ChosenUser
3

Vous pouvez également utiliser Copy Webpack Plugin si vous n'avez pas besoin de deux versions différentes, c'est-à-dire en supposant que vous voulez simplement servir un HTML différent avec le même main.bundle.js.

Le plugin est vraiment très simple (testé uniquement dans webpack v4):

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

const config = {
  plugins: [
    new CopyWebpackPlugin([
      { from: './src/example.html', to: './example.html' }
    ])
  ]
}

Ensuite, example.htmlvous pouvez charger la construction à partir de index.html. Par exemple:

<!DOCTYPE html>
<html
<head>
    ...
    <title>Example</title>
</head>
<body>
    <div id="container"> Show an example </div>
    <script src="main.bundle.js"></script>
</body>
</html>
F Lekschas
la source
1
existe-t-il un autre moyen possible d'utiliser CopyWebpackPlugin et d'ajouter le fichier bundle.js au fichier html via webpack au lieu de donner directement une référence au script dans le fichier html lui-même?
Sritam Jagadev
3

Pour utiliser plusieurs fichiers HTML en Webpackutilisant HtmlWebpackPlugin :

Modifiez le webpack.config.jsen incorporant directement le code ci-dessous.

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

let htmlPageNames = ['example1', 'example2', 'example3', 'example4'];
let multipleHtmlPlugins = htmlPageNames.map(name => {
  return new HtmlWebpackPlugin({
    template: `./src/${name}.html`, // relative path to the HTML files
    filename: `${name}.html`, // output HTML files
    chunks: [`${name}`] // respective JS files
  })
});

module.exports = {
  entry: {
    main: './js/main.js',
    example1: './js/example1.js',
    //... repeat until example 4
  },
  module: { 
       //.. your rules
  };
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      chunks: ['main']
    })
  ].concat(multipleHtmlPlugins)
  
};

Vous pouvez ajouter autant de pages HTML que nécessaire au htmlPageNamestableau. Assurez-vous que chaque fichier HTML et JS correspondant ont le même nom (le code ci-dessus suppose que).

RICHARD ABRAHAM
la source
0

Il existe une autre solution, en supposant Webpack ^ 4.44.1. Autrement dit, importer le HTML dans votre application JS / TS.

Exemple de webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');


module.exports = {
    entry: { app: './src/index.ts' },

    mode: 'development',
    devtool: 'inline-source-map',
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'Development',
            template: path.join(path.resolve(__dirname, 'src'), 'index.ejs')
        }),
    ],
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: 'ts-loader',
                include: [path.resolve(__dirname, 'src')],
                exclude: /node_modules/,
            },
            {
                test: /\.html$/i,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name].[ext]'
                        }
                    }
                ],
                // this exclude is required
                exclude: path.join(path.resolve(__dirname, 'src'), 'index.html')
            }
        ],
    },
    resolve: {
        extensions: ['.ts', '.js'],
    },
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 3900
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
};

Application correspondante

import './about.html';
    
console.log('this is a test'); 

index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Question</title>
</head>
<body>
     <a href="./about.html">About</a>
</body>
</html>

about.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>About</title>
</head>
<body>
    <p>This is an about page</p>
</body>
</html>

Webpack copiera about.html dans le dossier de sortie correspondant .

Alex Nolasco
la source
0
plugins: [
  ...templates.map(template => new HtmlWebpackPlugin(template))
]

Ce code vous aiderait si vous avez beaucoup de modèles :)

Pavel Rodionov
la source