Webpack 4 Upgrade — Подозреваемый плагин mini-css-extract — CSS никогда не загружается — Uncaught SyntaxError: Unexpected token

Я обновился с webpack v2 до webpack v4 - поскольку плагин извлечения текста больше не существует, я заменил его плагином MiniCssExtract, и мне пришлось отложить обновление, чтобы я мог обрабатывать имена файлов как функцию.

Теперь, когда это доступно, я запускаю веб-пакет, но тогда в моем приложении не будет работать ничего, ориентированное на css, я всегда буду получать: Uncaught SyntaxError: Unexpected token . в консоли.

Я пробовал даже самый простой CSS, и никакие файлы css не будут правильно выполняться в приложении.

Я попытался вернуться к простому css-loader и т. д., и они работают нормально, поэтому я думаю, что это как-то связано с тем, как настроен плагин mini-css-extract-plugin, или с чем-то глупым, что я пропустил.

У меня есть один файл для моей конфигурации темы:

const fs = require('fs');
const merge = require('webpack-merge');
const path = require('path');
const lessPlugins = require('../Theme/plugins/customLess');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const themes = ['green', 'yellow'];
const getThemeConfig = (isDevBuild, themeNameToPassInToLess) => {
    return {
        test: /\.(css|less)$/,
        use: ['style-loader',
            {
                loader: MiniCssExtractPlugin.loader,
                options: {
                    importLoaders: 1,
                    hmr: isDevBuild
                }
            },
            'css-loader',
            'postcss-loader',
            {
                loader: "less-loader",
                options: {
                    minimize: false,
                    plugins: [
                        lessPlugins
                    ],
                    globalVars: {
                        themeName: themeNameToPassInToLess
                    }
                }
            }]
    };
};

module.exports = {
    getThemeConfig,
    getCurrentTheme: () => {
        const AppSettings = JSON.parse(stripJsonComments(fs.readFileSync('./appsettings.json').toString()));
        if (AppSettings && AppSettings.ThemeConfig && AppSettings.ThemeConfig.ThemeName) {
            return AppSettings.ThemeConfig.ThemeName;
        }
        return 'default';
    },
    getThemeConfigs: (isDevBuild, sharedConfig, bundleOutputDir) => {
        const result = [];

        for (const theme of themes) {
            result.push(merge({
                entry: {
                    [theme]: './Theme/sites/default.less'
                },
                output: {
                    path: path.join(__dirname, bundleOutputDir),
                    filename: '[name].[chunkhash].css',
                    publicPath: '/dist/'
                },
                module: {
                    rules: [getThemeConfig(isDevBuild, theme)]
                }
            }, sharedConfig));
        }

        return result;
    }
};

и основной файл веб-пакета находится здесь:

const path = require('path');
const nodeExternals = require('webpack-node-externals');
const webpack = require('webpack');
const merge = require('webpack-merge');

const AutoPrefixer = require('autoprefixer');
const StatsWriterPlugin = require("webpack-stats-plugin").StatsWriterPlugin;
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const ForkTsCheckerNotifierWebpackPlugin = require('fork-ts-checker-notifier-webpack-plugin');

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const WebpackMd5Hash = require("webpack-md5-hash");

const bundleOutputDir = './wwwroot/dist';

const themeHelpers = require('./Webpack/themes');

let stats = {};

const cpus = require('os').cpus().length;
const settings = fs.existsSync('./webpackSettings.json') ?
    require('./webpackSettings.json') : {
        typeCheckerWorkers: Math.min(2, cpus),
        transpilerWorkers: Math.max(1, cpus - 3),
        typeCheckingOverlay: true,
    };

module.exports = (env, argv) => {
    console.log(env);
    const isDevBuild = !(env && env.prod);
    const sharedConfig = {
        devtool: isDevBuild ? 'source-map' : false,
        mode: isDevBuild ? 'development' : 'production',
        optimization: { minimize: !isDevBuild },
        stats: {
            modules: false
        },

        resolve: {
            extensions: ['.js', '.jsx', 'json', '.ts', '.tsx', '.modern'],
            modules: ['.', './', 'node_modules'],
            alias: {
                '../../theme.config$': path.join(__dirname, 'Theme/theme.config')
            }
        },
        externals: [nodeExternals()],
        module: {
            rules: [
                {
                    test: /\.(png|jpg|jpeg|gif)$/,
                    use: 'url-loader?limit=25000'
                },
                {
                    test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
                    loader: 'file-loader?name=public/fonts/[name].[ext]'
                }
            ]
        },

        plugins: [new MiniCssExtractPlugin({
                disable: isDevBuild,
                filename: (chunkData) => {
                    const name = chunkData.chunk.name.replace('js/build/', '').replace('components', 'base');
                    if (name.includes('admin') || name.includes('client') || name.includes('login')) {
                        return name + '-app.css';
                    }
                    return name + '.css';
                },
                chunkFilename: '[name].css'
            }),
            new ForkTsCheckerWebpackPlugin({
                workers: settings.typeCheckerWorkers,
                async: !settings.typeCheckingOverlay
            }),
            new webpack.LoaderOptionsPlugin({
                minimize: !isDevBuild,
                options: {
                    postcss: [AutoPrefixer]
                }
            }),
            new WebpackMd5Hash()
        ]
            .concat(settings.typeCheckingOverlay ? [] : [new ForkTsCheckerNotifierWebpackPlugin()])
            .concat(isDevBuild ? [
                // Plugins that apply in development builds only
                new webpack.DefinePlugin({
                    "process.env": {
                        NODE_ENV: JSON.stringify("development")
                    }
                })
            ] : [
                    // Plugins that apply in production builds only
                    new webpack.DefinePlugin({
                        "process.env": {
                            NODE_ENV: JSON.stringify("production")
                        }
                    })
                ])
    };

    const clientConfig = merge({
        entry: {
            'main-client': './ClientApp/boot.tsx',
            'login': './LoginApp/boot.tsx',
            'admin': './AdminApp/boot.tsx'
        },
        module: {
            rules: [{
                test: /\.tsx?$/,
                exclude: /node_modules/,
                include: /ClientApp|LoginApp|AdminApp|CommonApp/,
                use: [
                    `ifdef-loader?isDevBuild=${isDevBuild}`,
                    {
                        loader: 'awesome-typescript-loader',
                        options: {
                            silent: true,
                            transpileOnly: true,
                            useCache: true
                        }
                    }]
            },
            themeHelpers.getThemeConfig(isDevBuild, themeHelpers.getCurrentTheme())
            ]
        },
        output: {
            path: path.join(__dirname, bundleOutputDir),
            filename: isDevBuild ? '[name].js' : '[name].[chunkhash].js',
            publicPath: '/dist/'
        },
        plugins: [
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./wwwroot/dist/vendor-manifest.json')
            }),
            new webpack.LoaderOptionsPlugin({
                minimize: !isDevBuild,
                options: {
                    postcss: [AutoPrefixer]
                }
            }),
            new StatsWriterPlugin({
                filename: '../../webpackstats.json',
                transform(data) {
                    stats.assetsByChunkName = Object.assign({}, stats.assetsByChunkName, data.assetsByChunkName);
                    return JSON.stringify(stats, null, 4);
                }
            }),// Used by ScriptTagHelper
            new WebpackMd5Hash()
        ]

    }, sharedConfig);

    if (isDevBuild) {
        return clientConfig;
    }

    const themeConfigs = themeHelpers.getThemeConfigs(isDevBuild, sharedConfig, '.' + bundleOutputDir);
    console.log('ThemeConfigs Rules', themeConfigs[0].module.rules[0]);
    return [...themeConfigs, clientConfig];
};

person Tom    schedule 28.06.2019    source источник
comment
Похоже, что часть выходных данных — это ‹themename›.‹chunkhash›.css, например, yellow.baa1638b21372ac5c21a.css (см. этот файл, см. строку 7 первого фрагмента кода для имен тем. Эти файлы получают вывод, но на самом деле содержат webpackBootstrap js код, поэтому последующая обработка CSS завершается с ошибкой, потому что содержимое файлов не является допустимым css. Я хотел бы знать, сталкивался ли кто-нибудь еще с этим. Это сводит меня с ума   -  person Tom    schedule 02.07.2019


Ответы (1)


Пробовали ли вы вариант moduleFilename?

Сдача

new MiniCssExtractPlugin({
  disable: isDevBuild,
  filename: (chunkData) => {
      const name = chunkData.chunk.name.replace('js/build/', '').replace('components', 'base');
      if (name.includes('admin') || name.includes('client') || name.includes('login')) {
          return name + '-app.css';
      }
      return name + '.css';
  },
  chunkFilename: '[name].css'
}),

to

new MiniCssExtractPlugin({
  disable: isDevBuild,
  moduleFilename: (chunkData) => {
      const name = chunkData.name.replace('js/build/', '').replace('components', 'base');
      if (name.includes('admin') || name.includes('client') || name.includes('login')) {
          return name + '-app.css';
      }
      return name + '.css';
  }
}),
person KevinChappell    schedule 02.07.2019
comment
Привет, Кевин. Спасибо, я не видел такой возможности. - person Tom; 03.07.2019
comment
К сожалению, похоже, что это не работает, оно никогда не вызывается. ---', данные куска); if (chunkData.name.includes('admin') || chunkData.name.includes('client') || chunkData.name.includes('login')) { return 'app.css'; } return chunkData.name + '.css'; }``` - person Tom; 03.07.2019
comment
moduleFilename — это новая опция, опубликованная всего месяц назад, вам может потребоваться обновить mini-css-extract-plugin до 0.7.0, чтобы получить новую функцию. - person KevinChappell; 03.07.2019
comment
Спасибо, Кевин, это здорово. Раньше с помощью Extract-Text-плагина я мог сделать что-то подобное, чтобы объединить все точки входа в один файл css. include('admin') || chunkData.name.includes('client') || chunkData.name.includes('login')) { return 'app.css'; } - person Tom; 04.07.2019
comment
о, чтобы объединить файлы, я думаю, ваша логика должна быть в SplitChunksPlugin с использованием опции chunks или cacheGroup. ``` { оптимизация: { splitChunks: { cacheGroups: { app: { test: /admin|client|logion/, name: 'app', chunks: 'all', } } }, }, } ``` - person KevinChappell; 08.07.2019