Mehrere HTML-Dateien mit Webpack


87

Ich versuche etwas in einem Projekt zu tun, bei dem ich nicht sicher bin, ob es möglich ist, ob ich falsch liege oder etwas falsch verstehe. Wir verwenden Webpack und die Idee ist, mehr als eine HTML-Datei bereitzustellen.

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

Ich versuche dies durch Festlegen mehrerer Einstiegspunkte gemäß der Dokumentation :

Die Ordnerstruktur lautet:

/
|- 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>

Weiß jemand was ich falsch mache?

Vielen Dank.


Können Sie die Lösung dafür finden? Ich suche auch nach dem gleichen Anwendungsfall.
Monica

Antworten:


118

Sehen Sie einen Einstiegspunkt als Stamm eines Baums, der auf viele andere Elemente wie Javascript-Module, Bilder, Vorlagen usw. verweist. Wenn Sie mehr als einen Einstiegspunkt definieren, teilen Sie Ihre Assets grundsätzlich in sogenannte Chunks auf, um nicht Ihren gesamten Code und Ihre Assets in einem einzigen Bundle zu haben.

Ich denke, Sie möchten mehr als eine "index.html" für verschiedene Apps haben, die sich auch auf verschiedene Teile Ihrer Assets beziehen, die Sie bereits mit Ihren Einstiegspunkten definiert haben.

Das Kopieren einer index.html-Datei oder sogar das Generieren einer Datei mit Verweisen auf diese Einstiegspunkte wird vom Einstiegspunktmechanismus nicht behandelt - es ist umgekehrt. Ein grundlegender Ansatz für den Umgang mit HTML-Seiten ist die Verwendung von html-webpack-pluginHTML-Dateien, die nicht nur HTML-Dateien kopieren können, sondern auch über einen umfangreichen Mechanismus zum Erstellen von Vorlagen verfügen. Dies ist besonders hilfreich, wenn Sie möchten, dass Ihre Bundles mit einem Bundle-Hash versehen werden, der hübsch ist, um Probleme beim Zwischenspeichern des Browsers beim Aktualisieren Ihrer App zu vermeiden.

Da Sie ein Namensmuster definiert haben [id].bundle_[chunkhash].js, können Sie nicht mehr auf Ihr Javascript-Bundle verweisen, main.bundle.jsda es so etwas wie heißt main.bundle_73efb6da.js.

Schauen Sie sich das HTML-Webpack-Plugin an . Besonders relevant für Ihren Anwendungsfall:

Sie sollten wahrscheinlich am Ende so etwas haben (Warnung: nicht getestet)

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

Beachten Sie bitte den Namen des Einstiegspunkts im Chunks-Array. In Ihrem Beispiel sollte dies der Fall sein exampleEntry. Wahrscheinlich ist es auch eine gute Idee, Ihre Vorlagen in einen bestimmten Ordner zu verschieben, anstatt sie direkt im Stammordner zu speichern.

Hoffe das hilft.


4
Gute Erklärung, aber es stört mich immer noch, dass Sie für jede andere Seite, die Sie in Ihrem Projekt erstellen, "neues HTMLWebPlugin" aufrufen müssen.
Klewis

Jeder möchte nicht das 'neue HTMLWebPlugin' auf jeder Seite aufrufen. Brauche Alternative.
ChosenUser

3

Sie können das Copy Webpack Plugin auch verwenden, wenn Sie nicht zwei verschiedene Builds benötigen, dh vorausgesetzt, Sie möchten nur einen anderen HTML- Code mit demselben bereitstellenmain.bundle.js .

Das Plugin ist wirklich kinderleicht (nur in Webpack v4 getestet):

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

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

Dann example.htmlkönnen Sie den Build von laden index.html. Z.B:

<!DOCTYPE html>
<html
<head>
    ...
    <title>Example</title>
</head>
<body>
    <div id="container"> Show an example </div>
    <script src="main.bundle.js"></script>
</body>
</html>

1
Gibt es eine andere Möglichkeit, CopyWebpackPlugin zu verwenden und die Datei bundle.js über das Webpack zur HTML-Datei hinzuzufügen, anstatt direkt eine Skriptreferenz in der HTML-Datei selbst anzugeben?
Sritam Jagadev

3

So verwenden Sie mehrere HTML- Dateien bei der WebpackVerwendung von HtmlWebpackPlugin :

Ändern Sie das, webpack.config.jsindem Sie den folgenden Code direkt einbetten.

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)
  
};

Sie können dem htmlPageNamesArray beliebig viele HTML-Seiten hinzufügen . Stellen Sie sicher, dass jeder HTML-Code und jede entsprechende JS-Datei denselben Namen haben (der obige Code setzt dies voraus).


0

Es gibt eine andere Lösung, vorausgesetzt, Webpack ^ 4.44.1. Das heißt, Sie importieren den HTML-Code in Ihre JS / TS-App.

Beispiel 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'),
    },
};

Entsprechende App

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 kopiert about.html in den entsprechenden Ausgabeordner .


0
plugins: [
  ...templates.map(template => new HtmlWebpackPlugin(template))
]

Dieser Code würde helfen, wenn Sie viele Vorlagen haben :)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.