Beberapa file html menggunakan webpack


89

Saya mencoba melakukan sesuatu dalam sebuah proyek yang saya tidak yakin apakah itu mungkin, saya dengan cara yang salah atau salah paham. Kami menggunakan webpack, dan idenya adalah untuk menyajikan lebih dari satu file html.

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

Saya mencoba melakukannya dengan menyetel beberapa titik masuk, mengikuti dokumentasinya :

Struktur foldernya adalah:

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

Ada yang tahu apa yang saya lakukan salah?

Terima kasih.


Apakah Anda dapat menemukan solusi untuk ini? Saya juga mencari kasus penggunaan yang sama.
monica

Jawaban:


124

Lihat entrypoint sebagai root dari pohon yang mereferensikan banyak aset lain seperti modul javascript, gambar, template, dan sebagainya. Ketika Anda menentukan lebih dari satu entrypoint, pada dasarnya Anda membagi aset Anda menjadi apa yang disebut potongan agar tidak semua kode dan aset Anda dalam satu bundel tunggal.

Apa yang menurut saya ingin Anda capai adalah memiliki lebih dari satu "index.html" untuk aplikasi berbeda yang juga merujuk ke berbagai bagian aset Anda yang telah Anda tentukan dengan titik masuk Anda.

Menyalin file index.html atau bahkan membuat file dengan referensi ke entrypoint ini tidak ditangani oleh mekanisme entrypoint - sebaliknya. Pendekatan dasar untuk menangani halaman html adalah menggunakan html-webpack-pluginyang tidak hanya dapat menyalin file html tetapi juga memiliki mekanisme ekstensif untuk pembuatan template. Ini sangat membantu jika Anda ingin bundel Anda diakhiri dengan hash bundel yang cukup untuk menghindari masalah cache browser saat Anda memperbarui aplikasi Anda.

Karena Anda telah menentukan pola nama karena [id].bundle_[chunkhash].jsAnda tidak dapat lagi mereferensikan bundel javascript Anda main.bundle.jskarena akan disebut sesuatu seperti main.bundle_73efb6da.js.

Silakan lihat di html-webpack-plugin . Sangat relevan untuk kasus penggunaan Anda:

Anda mungkin harus memiliki sesuatu seperti itu pada akhirnya (peringatan: tidak diuji)

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

Harap berhati-hati untuk mereferensikan nama entrypoint dalam larik chunks, jadi dalam contoh Anda ini seharusnya exampleEntry. Mungkin juga merupakan ide bagus untuk memindahkan templat Anda ke folder tertentu daripada menyimpannya langsung di dalam folder src root.

Semoga ini membantu.


4
Penjelasan yang bagus tetapi masih mengganggu saya bahwa Anda harus memanggil 'HTMLWebPlugin baru' untuk setiap halaman berbeda yang Anda buat dalam proyek Anda.
klewis

Setiap orang tidak suka menyebut 'HTMLWebPlugin baru' setiap halaman. Butuh alternatif.
ChosenUser

4

Untuk menggunakan Beberapa file HTML dalam Webpackmenggunakan HtmlWebpackPlugin :

Ubah webpack.config.jsdengan langsung menyematkan kode di bawah ini.

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

Anda dapat menambahkan halaman HTML sebanyak yang diperlukan ke htmlPageNamesarray. Pastikan bahwa setiap HTML dan file JS yang sesuai memiliki nama yang sama (Kode di atas mengasumsikan demikian).


Ini adalah pendekatan yang bagus. Meskipun menggunakan sintaks ES6. Lihat disini .
robev

3

Anda juga dapat menggunakan Plugin Copy Webpack jika Anda tidak memerlukan dua build yang berbeda, misalnya, dengan asumsi Anda hanya ingin menyajikan HTML yang berbeda dengan yang sama main.bundle.js.

Plugin ini sangat sederhana (hanya diuji di webpack v4):

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

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

Kemudian example.htmlAnda dapat memuat build dari index.html. Misalnya:

<!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
apakah ada cara lain yang mungkin untuk menggunakan CopyWebpackPlugin dan menambahkan file bundle.js ke file html melalui webpack daripada langsung memberikan referensi skrip di file html itu sendiri?
Sritam Jagadev

0

Ada solusi lain, dengan asumsi Webpack ^ 4.44.1. Artinya, mengimpor HTML di aplikasi JS / TS Anda.

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

Aplikasi yang sesuai

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 akan menyalin about.html ke folder keluaran yang sesuai .


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

Kode ini akan membantu jika Anda memiliki banyak template :)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.