Независимые чанки с веб-пакетом

Я строю библиотеку компонентов, и я использую Webpack, чтобы связать ее. Некоторые компоненты опираются только на HTML-шаблоны, CSS и JavaScript, которые я написал, но некоторые компоненты требуют внешних библиотек.

То, что я хотел бы достичь, это vendor.js это необязательно включать, если компонент, который вы хотите использовать, нуждается в нем.

Например, если пользователю нужен только компонент без зависимостей от поставщика, достаточно, чтобы он использовал main.bundle.js который содержит только мой собственный код.

В моем index.jsУ меня есть следующий импорт:

import { Header } from './components/header/header.component';
import { Logotype } from './components/logotype/logotype.component';
import { Card } from './components/card/card.component';
import { NavigationCard } from './components/navigation-card/navigation-card.component';
import { AbstractComponent } from './components/base/component.abstract';
import { Configuration } from './system.config';

import 'bootstrap-table';

import './scss/base.scss';

Весь этот импорт - мой, ожидайте bootstrap-table,

Я настроил Webpack следующим образом:

const webpack = require('webpack');

const path = require('path');

const ExtractTextPlugin = require('extract-text-webpack-plugin');

const extractScss = new ExtractTextPlugin({
    filename: "[name].bundle.css"
});

module.exports = {
    entry:  {
        main: './src/index.ts'
    },
    output: {
        path: path.resolve(__dirname, 'dist/release'),
        filename: "[name].bundle.js",
        chunkFilename: "[name].bundle.js"
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor', // Specify the common bundle's name.
            minChunks: function (module) {
                // Here I would like to tell Webpack to give 
                // each bundle the ability to run independently
                return module.context && module.context.indexOf('node_modules') >= 0;
            }
        }),
        extractScss
    ],
    devtool: "source-map",
    resolve: {
        // Add `.ts` as a resolvable extension.
        extensions: ['.webpack.js', '.web.js', '.ts', '.js', '.ejs']
    },
    module: {
        rules: [
            // All files with a '.ts' extension will be handled by 'awesome-typescript-loader'.
            { test: /\.ts?$/, exclude: /node_modules/, loader: "awesome-typescript-loader" },

            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" },

            // Allows for templates in separate ejs files
            {test: /\.ejs$/, loader: 'ejs-compiled-loader'},

            {
                test: /\.scss$/,
                use: extractScss.extract({
                use: [{
                    loader: 'css-loader', options: {
                        sourceMap: true
                    }
                }, {
                    loader: 'sass-loader', options: {
                        soureMap: true
                    }
                }]
            })}
        ]
    }
}

Это приводит к двум .js файлы и один .css, Тем не менее, общие функции загрузки веб-пакетов находятся в vendor.jsи это делает мой основной непригодным, если я сначала не включаю продавца, а это не всегда нужно.

Подводя итог, если пользователю нужен только нижний колонтитул (без внешних зависимостей), этого будет достаточно:
<script src="main.bundle.js"></script>

Если пользователь хочет использовать таблицу, которая имеет внешнюю зависимость, он должен включить оба:
<script src="vendor.js"></script>
<script src="main.bundle.js"></script>

Прямо сейчас, включая только main.bundle.js дает мне эту ошибку:
Uncaught ReferenceError: webpackJsonp is not defined,

Мне известно, что я могу извлечь все обычные функции, добавив их после того, как в конфигурации Webpack будет создан мой блок вендора:

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

Но этот подход все еще требует, чтобы пользователь включил два .js файлы.

Как я могу добиться этого? Кажется, что он отличается только на 2 КБ, когда я не извлекаю общие модули, как я делаю выше, и это нормально для меня.

1 ответ

Оказывается, это очень легко сделать, если вы можете выдержать некоторую ручную работу и действительно понять, что делает Webpack (чего я не делал). Я решил это так:

const webpack = require('webpack');

const path = require('path');

const ExtractTextPlugin = require('extract-text-webpack-plugin');

const extractScss = new ExtractTextPlugin({
    filename: "[name].bundle.css"
});

module.exports = {
    entry:  {
        main: './src/index.ts',
        vendor: './src/vendor/vendor.ts'
    },
    output: {
        path: path.resolve(__dirname, 'dist/release'),
        filename: "[name].bundle.js",
        chunkFilename: "[name].bundle.js"
    },
    plugins: [
        extractScss
    ],
    devtool: "source-map",
    resolve: {
        // Add `.ts` as a resolvable extension.
        extensions: ['.webpack.js', '.web.js', '.ts', '.js', '.ejs']
    },
    module: {
        rules: [
            // All files with a '.ts' extension will be handled by 'awesome-typescript-loader'.
            { test: /\.ts?$/, exclude: /node_modules/, loader: "awesome-typescript-loader" },

            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" },

            // Allows for templates in separate ejs files
            {test: /\.ejs$/, loader: 'ejs-compiled-loader'},

            {
                test: /\.scss$/,
                use: extractScss.extract({
                use: [{
                    loader: 'css-loader', options: {
                        sourceMap: true
                    }
                }, {
                    loader: 'sass-loader', options: {
                        soureMap: true
                    }
                }]
            })}
        ]
    }
}

В vendor.tsЗатем я просто импортирую любые зависимости от поставщика:

import 'jquery';
import 'bootstrap-table';

В результате получается два разных файла, оба имеют логику начальной загрузки Webpacks.

Надеюсь, это кому-нибудь поможет.

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