最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

vue.js - Extract css per entry point in webpack - Stack Overflow

programmeradmin0浏览0评论

Anyway to tell webpack in a project with multiple entries to include only respective css for each entry?

Seems like it extracts all css across all entries, puts them under vendor.css and includes that css into all of the entries. And I can't figure out how to tell it to separate the css per entry.

It's a Vue3 project, but the solution should be webpack specific.

Anyway, my vue.config.js goes something like this:

module.exports = {
    ...
    pages:{
        entry1:{
            entry:"./src/entry/entry1.js",
            template:"public/entry1.html"
        },
        entry2:{
            entry:"./src/entry/entry2.js",
            template:"public/entry2.html"
        }
    },
    ...

    configureWebpack:{
        ...
    }
}

entry1.js:

import css1.css
...

entry2.js:

import css2.css
...

Now I need to build entry1.html with only styles from css1.css included and entry2.html with only styles from css2.css included.

Instead webpack combines all styles from both css1.css and css2.css into a single file and includes that resulting file into the both htmls.

I was trying to play around with MiniCssExtractPlugin configs and chunk naming but no luck so far.

Anyway to tell webpack in a project with multiple entries to include only respective css for each entry?

Seems like it extracts all css across all entries, puts them under vendor.css and includes that css into all of the entries. And I can't figure out how to tell it to separate the css per entry.

It's a Vue3 project, but the solution should be webpack specific.

Anyway, my vue.config.js goes something like this:

module.exports = {
    ...
    pages:{
        entry1:{
            entry:"./src/entry/entry1.js",
            template:"public/entry1.html"
        },
        entry2:{
            entry:"./src/entry/entry2.js",
            template:"public/entry2.html"
        }
    },
    ...

    configureWebpack:{
        ...
    }
}

entry1.js:

import css1.css
...

entry2.js:

import css2.css
...

Now I need to build entry1.html with only styles from css1.css included and entry2.html with only styles from css2.css included.

Instead webpack combines all styles from both css1.css and css2.css into a single file and includes that resulting file into the both htmls.

I was trying to play around with MiniCssExtractPlugin configs and chunk naming but no luck so far.

Share Improve this question asked Nov 19, 2024 at 10:55 vir usvir us 10.8k6 gold badges68 silver badges76 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

Ok, the solution was as simple as setting optimization.splitChunks.minChunks = 2 (since I have two entries):

configureWebpack: {
    optimization: {
        splitChunks: {
            ...
            minChunks: 2, // <- this was the fix. Indicates that modules must be imported at least twice before merging them into a common chunk
    }
}

split-chunks-plugin doc reference

You can use the html-bundler-webpack-plugin which allow exactly that you need.

Using the Bundler Plugin, an entry point is an HTML template. All your source asset files (scripts, styles, images, etc.) can be specified directly in the HTML template using <script> and <link> tags. The plugin resolves source files of assets in templates and replaces them with correct output URLs in the generated HTML. The resolved assets will be processed via Webpack plugins/loaders and placed into the output directory.

For example, there is the HTML template src/entry/home.html:

<!DOCTYPE html>
<html>
<head>
  <!-- relative path to CSS/SCSS source file src/entry/home.css -->
  <link href="./home.css" rel="stylesheet">
  <!-- relative path to JS source file src/entry/home.js -->
  <script src="./home.js" defer="defer"></script>
</head>
<body>
  <h1>Home</h1>
</body>
</html>

there is other HTML template src/entry/about.html:

<!DOCTYPE html>
<html>
<head>
  <!-- relative path to CSS/SCSS source file src/entry/about.css -->
  <link href="./about.css" rel="stylesheet">
  <!-- relative path to JS source file src/entry/about.js-->
  <script src="./about.js" defer="defer"></script>
</head>
<body>
  <h1>About</h1>
</body>
</html>

Webpack config:

const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
  },

  plugins: [
    new VueLoaderPlugin(),
    new HtmlBundlerPlugin({
      entry: {
        index: 'src/entry/home.html', // save generated HTML into dist/index.html
        about: 'src/entry/about.html', // save generated HTML into dist/about.html
      },
      js: {
        filename: 'js/[name].[contenthash:8].js', // JS output filename
      },
      css: {
        filename: 'css/[name].[contenthash:8].css', // CSS output filename
      },
    }),
  ],
  
  module: {
      rules: [
        {
          test: /\.vue$/i,
          use: ['vue-loader'],
        },
        {
          test: /\.s?css$/,
          use: ['css-loader', 'sass-loader'], // you can use both SCSS and CSS
        },
      ],
    },
};

The HtmlBundlerPlugin replaces the functionality of many plugins and loaders:

  • html-webpack-plugin
  • mini-css-extract-plugin
  • and many others

The generated HTML contains output URLs:

dist/index.html:

<!DOCTYPE html>
<html>
<head>
  <link href="css/home.1234abcd.css" rel="stylesheet">
  <script src="js/home.adbc1234.js" defer="defer"></script>
</head>
<body>
  <h1>Home</h1>
</body>
</html>

dist/about.html:

<!DOCTYPE html>
<html>
<head>
  <link href="css/about.1234abcd.css" rel="stylesheet">
  <script src="js/about.adbc1234.js" defer="defer"></script>
</head>
<body>
  <h1>About</h1>
</body>
</html>
发布评论

评论列表(0)

  1. 暂无评论