Nhiều tệp html sử dụng webpack


87

Tôi đang cố gắng thực hiện một điều gì đó trong một dự án mà tôi không chắc liệu nó có khả thi không, tôi đang làm sai cách hoặc hiểu sai điều gì đó. Chúng tôi đang sử dụng webpack và ý tưởng là cung cấp nhiều hơn một tệp html.

localhost: 8181 -> phục vụ index.html
localhost: 8181 / example.html -> phục vụ example.html

Tôi đang cố gắng thực hiện điều đó bằng cách đặt nhiều điểm vào, theo tài liệu :

Cấu trúc thư mục là:

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

Ai đó biết tôi đang làm gì sai?

Cảm ơn bạn.


Bạn có thể tìm thấy giải pháp cho điều này? Tôi cũng đang tìm kiếm trường hợp sử dụng tương tự.
monica

Câu trả lời:


118

Xem entrypoint là gốc của cây tham chiếu đến nhiều nội dung khác như mô-đun javascript, hình ảnh, mẫu, v.v. Khi bạn xác định nhiều điểm nhập, về cơ bản, bạn chia nội dung của mình thành các phần được gọi là phần để không có tất cả mã và nội dung của bạn trong một gói duy nhất.

Những gì tôi nghĩ bạn muốn đạt được là có nhiều hơn một "index.html" cho các ứng dụng khác nhau cũng đề cập đến các phần khác nhau của nội dung mà bạn đã xác định với các điểm nhập của mình.

Việc sao chép tệp index.html hoặc thậm chí tạo tệp có tham chiếu đến các điểm nhập này không được xử lý bởi cơ chế điểm nhập - đó là cách khác. Một cách tiếp cận cơ bản để xử lý các trang html là sử dụng html-webpack-pluginnó không chỉ có thể sao chép các tệp html mà còn có một cơ chế mở rộng để tạo khuôn mẫu. Điều này đặc biệt hữu ích nếu bạn muốn các gói của mình được gắn với một hàm băm gói đẹp để tránh các vấn đề về bộ nhớ đệm của trình duyệt khi bạn cập nhật ứng dụng của mình.

Khi bạn đã xác định một mẫu tên, [id].bundle_[chunkhash].jsbạn không còn có thể tham chiếu đến gói javascript của mình nữa main.bundle.jsvì nó sẽ được gọi là một cái gì đó giống như vậy main.bundle_73efb6da.js.

Hãy xem html-webpack-plugin . Đặc biệt phù hợp với trường hợp sử dụng của bạn:

Cuối cùng thì có lẽ bạn nên có thứ gì đó tương tự (cảnh báo: không được kiểm tra)

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

Hãy lưu ý tham chiếu tên của điểm nhập trong mảng khối, vì vậy trong ví dụ của bạn, điều này nên như vậy exampleEntry. Có lẽ cũng nên di chuyển các mẫu của bạn vào một thư mục cụ thể thay vì đặt chúng trực tiếp bên trong thư mục gốc src.

Hi vọng điêu nay co ich.


4
Giải thích tốt nhưng tôi vẫn thấy phiền rằng bạn phải gọi 'HTMLWebPlugin mới' cho mỗi trang khác nhau mà bạn tạo trong dự án của mình.
klewis

Mọi người đều không thích gọi 'HTMLWebPlugin mới' cho mỗi trang. Cần thay thế.
ChosenUser

3

Bạn cũng có thể sử dụng Copy Webpack Plugin nếu bạn không cần hai bản dựng khác nhau, tức là giả sử rằng bạn chỉ muốn phân phát một HTML khác với cùng một bản dựng main.bundle.js.

Plugin thực sự rất đơn giản (chỉ được thử nghiệm trong webpack v4):

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

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

Sau đó, example.htmlbạn có thể tải bản dựng từ index.html. Ví dụ:

<!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
có cách nào khác có thể sử dụng CopyWebpackPlugin và thêm tệp Bundle.js vào tệp html thông qua webpack thay vì trực tiếp cung cấp tham chiếu tập lệnh trong chính tệp html không?
Sritam Jagadev

3

Để sử dụng Nhiều tệp HTMLWebpack bằng HtmlWebpackPlugin :

Sửa đổi webpack.config.jsbằng cách nhúng trực tiếp đoạn mã dưới đây.

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

Bạn có thể thêm nhiều trang HTML theo yêu cầu vào htmlPageNamesmảng. Đảm bảo rằng mỗi tệp HTML và tệp JS tương ứng có cùng tên (Đoạn mã trên giả định điều đó).


0

Có một giải pháp khác, giả sử Webpack ^ 4.44.1. Đó là, nhập HTML trong ứng dụng JS / TS của bạn.

Mẫu 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'),
    },
};

Ứng dụng tương ứng

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 sẽ sao chép about.html vào thư mục đầu ra tương ứng .


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

Mã này sẽ hữu ích nếu bạn có nhiều mẫu :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.