Как извлечь CSS в таблицу стилей `crit.css` с помощью оператора` import` с Webpack? - PullRequest
1 голос
/ 20 июня 2019

Фон

Наше веб-приложение следует шаблону проектирования на основе компонентов, где каждый компонент содержит шаблон, частичку Sass и модуль JavaScript, например: -

components/action_button/_action_button.html.erb
                        /_action_button.scss
                        /action_button.js

JavaScriptmodule import s, часть Sass компонента, и шаблон отображается через Rails.В Webpack настроено несколько загрузчиков и плагинов для компиляции стилей и извлечения (через mini-css-extract-plugin) результирующего CSS в отдельную таблицу стилей для каждой точки входа, например: -

home.js => home.js, home.css
search.js => search.js, search.css

Компоненты import edв точки входа, основанные на использовании (т. е. если action_button присутствует в 'home', то оно отображается где-то в представлении, а import '~/components/action_button/action_button.js'; объявляется в home.js.

Проблема

Чтобы улучшить процесс загрузки страницы, мы вручную @import выбираем несколько компонентов Sass компонента в точку входа critical.scss, затем выведенный CSS встраивается в <head> документа, и полные таблицы стилей загружаются асинхронно.

В идеале мы хотели бы сделать это динамически, и один из методов, о котором я подумал, - обозначить критичность компонента с помощью оператора import. Возможно, с помощью пользовательского загрузчика?: -

import 'critical-loader!~/components/action_button/action_button.js';

Проблема в том, что я мало представляю, как будет работать этот загрузчик Webpack. Я хочу, чтобы он оставил все существующие правила на месте, но перенаправить извлеченный CSS из Sass partials import ed изнутри в critical.css.

Кто-нибудь знает о существующем решении или знает, с чего начатьтакая проблема?

1 Ответ

0 голосов
/ 21 июня 2019

Вы можете использовать MiniCssExtractPlugin, чтобы при импорте файла CSS в ваш файл JS веб-пакет распаковывался в файл CSS.Ниже мой конфиг

const path = require("path");
const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const WebpackShellPlugin = require('webpack-shell-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

process.traceDeprecation = true;

module.exports = {
    entry: {
        admin: "./React/js/App/Modules/Admin/admin.js",
        client: "./React/js/App/Modules/Client/client.js",
        login: "./React/js/EntryPoint/Modules/Admin/Account/Login/Login.js",
        password: "./React/js/EntryPoint/Modules/Admin/Account/Password/Password.js",
        manageaccount: "./React/js/EntryPoint/Modules/Admin/Account/Index.js",
        categories: "./React/js/EntryPoint/Modules/Admin/Categories/Categories.js",
        tag: "./React/js/EntryPoint/Modules/Admin/Tag/Tag.js",
        post: "./React/js/EntryPoint/Modules/Admin/Post/Post.js",
        comment: "./React/js/EntryPoint/Modules/Admin/Comment/Comment.js",
        portal: "./React/js/EntryPoint/Modules/Admin/Portal/PortalIndex.js",
        ClientIndex: "./React/js/EntryPoint/Modules/Client/Index/ClientIndex.js",
        adminSettings: "./React/js/EntryPoint/Modules/Admin/Settings/Settings.js",
        socialLinks: "./React/js/EntryPoint/Modules/Shared/SocialLinks.js"
    },
    output: {
        path: path.resolve(__dirname, "wwwroot/dist"),
        filename: "[name].js",
        publicPath: "/dist/"
    },
    optimization: {
        minimizer: [
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                sourceMap: false,
                extractComments: 'all',
                uglifyOptions: {
                    compress: true,
                    output: null
                }
            }),
            new OptimizeCSSAssetsPlugin({
                cssProcessorOptions: {
                    safe: true,
                    discardComments: {
                        removeAll: true,
                    },
                },
            })
        ]
    },
    plugins: [
        new webpack.ContextReplacementPlugin(/\.\/locale$/, 'empty-module', false, /jsx$/),
        new webpack.LoaderOptionsPlugin({
            options: {}
        }),
        new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename: "[id].css"
        }),
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery",
            Popper: ['popper.js', 'default']
        }),
        new CompressionPlugin({
            test: /\.(js|css)/
        }),
        new UglifyJsPlugin(),
        new WebpackShellPlugin({
            onBuildStart: ['echo "Starting postcss command"'],
            onBuildEnd: ['postcss --dir wwwroot/dist wwwroot/dist/*.css']
        })
    ],
    resolve: {
        modules: [
            path.resolve('./React/js/App'),
            path.resolve('./React/js/App/Modules/Client'),
            path.resolve('./React/js/App/Modules/Adnmin'),
            path.resolve('./node_modules')
        ]
    },
    module: {
        rules: [{
                test: /\.scss$/,
                use: [
                    'style-loader',
                    MiniCssExtractPlugin.loader,
                    {
                        loader: "css-loader",
                        options: {
                            minimize: true,
                            sourceMap: true
                        }
                    },
                    {
                        loader: "sass-loader"
                    }
                ]
            },
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                loader: ["babel-loader", "eslint-loader"]
            },
            {
                test: /\.(jpe?g|png|gif)$/i,
                loader: "file-loader"
            },
            {
                test: /\.(woff|ttf|otf|eot|woff2|svg)$/i,
                loader: "file-loader"
            }
        ]
    }
};
...