Несколько файлов html с использованием webpack

87

Я пытаюсь сделать что-то в проекте, но я не уверен, что это возможно, я ошибаюсь или что-то не понимаю. Мы используем webpack, и идея состоит в том, чтобы обслуживать более одного файла HTML.

localhost: 8181 -> обслуживает index.html
localhost: 8181 / example.html -> обслуживает example.html

Я пытаюсь сделать это, установив несколько точек входа, следуя документации :

Структура папок:

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

Кто-нибудь знает, что я делаю не так?

Спасибо.

мигелитомп
источник
Вы можете найти для этого решение? Я также ищу такой же вариант использования.
моника

Ответы:

118

Считайте точку входа корнем дерева, которое ссылается на многие другие ресурсы, такие как модули javascript, изображения, шаблоны и так далее. Когда вы определяете более одной точки входа, вы в основном разделяете свои ресурсы на так называемые блоки, чтобы не иметь весь ваш код и ресурсы в одном пакете.

Я думаю, вы хотите достичь более одного "index.html" для разных приложений, которые также относятся к разным фрагментам ваших ресурсов, которые вы уже определили с помощью своих точек входа.

Копирование файла index.html или даже его создание со ссылками на эти точки входа не обрабатывается механизмом точек входа - это наоборот. Базовый подход к работе с html-страницами заключается в использовании, html-webpack-pluginкоторый не только может копировать html-файлы, но также имеет обширный механизм для создания шаблонов. Это особенно полезно, если вы хотите, чтобы ваши пакеты были дополнены хешем пакета, который позволяет избежать проблем с кешированием браузера при обновлении приложения.

Поскольку вы определили шаблон имени, [id].bundle_[chunkhash].jsвы больше не можете ссылаться на свой пакет javascript, main.bundle.jsпоскольку он будет называться примерно так main.bundle_73efb6da.js.

Взгляните на html-webpack-plugin . Особенно актуально для вашего варианта использования:

Вероятно, у вас должно получиться что-то подобное в конце (предупреждение: не проверено)

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

Не забывайте ссылаться на имя точки входа в массиве chunks, поэтому в вашем примере это должно быть exampleEntry. Вероятно, также неплохо переместить шаблоны в определенную папку вместо того, чтобы помещать их непосредственно в корневую папку src.

Надеюсь это поможет.

Андреас Ягле
источник
4
Хорошее объяснение, но меня все еще беспокоит, что вам нужно вызывать «новый HTMLWebPlugin» для каждой отдельной страницы, которую вы создаете в своем проекте.
klewis 03
Все не любят называть каждую страницу «новым HTMLWebPlugin». Нужна альтернатива.
ChosenUser
3

Вы также можете использовать плагин Copy Webpack, если вам не нужны две разные сборки, т. Е. Если вы просто хотите обслуживать другой HTML с тем же самым main.bundle.js.

Плагин действительно очень простой (протестирован только в webpack v4):

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

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

Затем example.htmlвы можете загрузить сборку из index.html. Например:

<!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
есть ли другой способ использовать CopyWebpackPlugin и добавить файл bundle.js в файл html через веб-пакет вместо того, чтобы напрямую указывать ссылку на скрипт в самом файле html?
Sritam Jagadev
3

Чтобы использовать несколько файлов HTML при Webpackиспользовании HtmlWebpackPlugin :

Измените webpack.config.js, напрямую вставив приведенный ниже код.

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

Вы можете добавить в htmlPageNamesмассив любое количество HTML-страниц . Убедитесь, что каждый HTML-файл и соответствующий JS-файл имеют одинаковое имя (это предполагается в приведенном выше коде).

РИЧАРД АВРААМ
источник
0

Есть другое решение, предполагающее, что Webpack ^ 4.44.1. То есть импорт HTML в ваше приложение JS / TS.

Пример 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'),
    },
};

Соответствующее приложение

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 скопирует файл about.html в соответствующую папку вывода .

Алекс Ноласко
источник
0
plugins: [
  ...templates.map(template => new HtmlWebpackPlugin(template))
]

Этот код поможет, если у вас много шаблонов :)

Павел Родионов
источник