Webpack 4 - Миграция из CommonsChunkPlugin с помощью SplitChunksPlugin

У нас есть традиционное приложение для сервера (не SPA), где каждая страница дополняется с помощью vuejs.

Наша существующая конфигурация webpack 3

webpack.config.js

var webpack = require('webpack')
var path = require('path')

const ExtractTextPlugin = require('extract-text-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
    entry: {
        shared: './shared.js',
        pageA: './pageA.js',
        // pageB: './pageB.js',
        // pageC: './pageC.js',
        // etc
    },

    resolve: {
        alias: { vue: 'vue/dist/vue.esm.js' },
    },

    output: {
        path: path.join(__dirname, './dist'),
        filename: '[name].js',
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                exclude: /node_modules/,
                use: ExtractTextPlugin.extract({
                    use: [
                        {
                            loader: 'css-loader',
                            query: {
                                sourceMap: true,
                            },
                        },
                    ],
                }),
            },
        ],
    },

    plugins: [
        new CleanWebpackPlugin('./dist'),

        new webpack.optimize.CommonsChunkPlugin({
            name: ['shared'],
            minChunks: Infinity,
        }),

        new webpack.optimize.CommonsChunkPlugin({
            name: 'runtime',
        }),

        new ExtractTextPlugin('[name].css'),

        new CopyWebpackPlugin([{ from: 'index.html', to: '.' }]),
    ],
}

shared.js

// import shared dependencies & pollyfills
var vue = require('vue')

// import global site css file
require('./shared.css')

// initialize global defaults
// vue.setDefaults(...)

console.log('shared', { vue })

pageA.js

var vue = require('vue')

// only this page uses axios
var axios = require('axios')

console.log('pageA', { vue, axios })

shared.css

body {
    background-color: aquamarine;
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- included on every page-->
    <link rel="stylesheet" href="shared.css">
</head>
<body>
    <!-- included on every page-->
    <script src="runtime.js"></script>
    <script src="shared.js"></script>

    <script src="pageA.js"></script>
</body>
</html>

С этой настройкой

1) runtime.js содержит загрузчик веб-пакетов, поэтому любые изменения shared.js не вызывает pageA.js быть кешированным и наоборот

2) shared.js содержит какие-либо общие зависимости (в этом случае vue), а также любая общая глобальная инициализация для каждой страницы (настройка vue по умолчанию и т. д.). Также он указывает, что мы импортируем наш общий глобальный файл CSS.

3) pageA.js не содержит зависимостей, импортированных в shared.js (vue в этом случае) но содержит зависимости, которые он импортирует (axios в этом случае).

Нам не удалось воспроизвести эту настройку с помощью SplitChunksPlugin

1) SplitChunksPlugin кажется, не позволяет точку входа в качестве точки разделения.

2) Все примеры разбили ВСЕ зависимости узла модуля на кусок вендора. Это не работает для нас, так как у нас есть сотни страниц, но только некоторые импортируют графическую библиотеку или момент и т. Д. Мы не хотим, чтобы эта графическая библиотека или момент были включены в shared.js так как он будет загружен для всех страниц.

3) Также не было ясно, как разбить среду выполнения на собственный файл

SplitChunksPlugin Похоже, что он предназначен для SPA, где javascript может быть загружен по требованию. Сценарий, который мы трагируем, все еще поддерживается?

2 ответа

Вы пытаетесь перейти на webpack 4?

Я нахожу optimisation cacheGroups test option хорошо работает, чтобы быть конкретным о том, что идет куда.

optimization: {
  splitChunks: {
    cacheGroups: {
      shared: {
        test: /node_modules[\\/](?!axios)/,
        name: "shared",
        enforce: true,
        chunks: "all"
      }
    }
  }
}

Загрузит все из узловых модулей (кроме axios) и поэтому должен быть включен как часть точки входа вашей страницы.

Если вы хотите, чтобы webpack разделял какой-либо компонент, вам нужно будет асинхронно импортировать его из основного файла ввода. Я использовал Bundle-Loader, чтобы сделать это, тогда у меня есть:

В моем webpack.config.js

optimization: {
  splitChunks: {
    chunks: 'all'
  },
  mergeDuplicateChunks: true,
}
module: {
  rules: [
    {
      test: /\.bundle\.js$/, //yes my output file contains the bundle in its name
      use: {
        loader: 'bundle-loader', options: {lazy: true}
      }
    }
  ]
}

В моем файле входа.

//this code will replace the line where you are importing this component
let Login;

// this method will go inside your component
componentWillMount() {
    require("bundle-loader!./ui/Login.jsx")((loginFile) => {
        Login = loginFile.default;
        this.setState({ loginLoaded: true });
    });
}

Если вы не хотите его использовать, есть еще несколько способов импортировать файл в асинхронном режиме.

Другие вопросы по тегам