Сборка Webpack 4 с Angular 7 дает проблему с загрузчиком sass при попытке доступа к node_modules

Я работал над обновлением Angular v4 до v7. Есть некоторые критические изменения, связанные с переходом от .angular-cli.json к angular.json и их структурой. А также обновление версий angular и webpack имеет свое влияние.

В Angular 4 он отлично работал с настраиваемым конструктором веб-пакетов, но при обновлении до v7 есть свои сложности. Также стоит упомянуть, что попытка сборки без @imports в scss на используемых мной node_modules тоже работает должным образом. Итак, я вижу, что проблема связана с путем к / от веб-пакета.

Основная проблема, с которой мы сейчас сталкиваемся, заключается в том, что загрузчик sass жалуется на @import 'path/to/file', что он его не находит, а затем завершает сборку с ошибкой.

Выполнение ng serve и ng build работает без каких-либо проблем, но выполнение сборки с пользовательским веб-пакетом не удается, потому что не находит путь.

Я получаю следующую ошибку:

ОШИБКА в сборке модуля (из ./node_modules/sass-loader/lib/loader.js): @import '../../styles/src/abstracts/_mixins.scss "; ^ Файл для импорта не найден или не читается : '../../styles/src/abstracts/_mixins.scss "; Родительская таблица стилей: стандартный ввод в / Путь / к / проекту (строка 4, столбец 1)

Я также попытался выполнить npm link из пакета с моего локального компьютера в node_modules без какого-либо прогресса.

Пакеты - это компоненты, которые я импортирую в свои проекты, это только пакеты с компонентами и их scss.

Файлы конфигурации webpack выглядят так:

* webpack.config.app.prod.js *

var webpackMerge = require('webpack-merge');
var prod = require('./webpack.config.prod');
var AotPlugin = require('@ngtools/webpack').AngularCompilerPlugin;

module.exports = webpackMerge.strategy({
    plugins: 'prepend'
})(prod.config, {
    entry: './src/main-wp.editor.aot.ts',
    output: {
        filename: 'editor.bundle.js',
        chunkFilename: '[id].chunk.js',
        library: '_' + 'child',
        libraryTarget: 'jsonp'
    },
    plugins: [
        new AotPlugin({
            tsConfigPath: 'tsconfig.aot.json',
            entryModule: './src/app/modules/app.module#EditorModule',
            debug: true
        })
    ]
});

* webpack.config.prod.js *

var path = require('path');

var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var commonConfig = require('./webpack.config.common');
var UglifyJsPlugin = require("uglifyjs-3-webpack-plugin");

module.exports = {
    config: webpackMerge(commonConfig, {
        output: {
            path: path.resolve(__dirname, 'dist'),
            publicPath: '/',
            filename: 'bundle.js',
            chunkFilename: '[id].[hash].chunk.js'
        },
        module: {
            rules: [
                {
                    test: /\.ts$/,
                    use: ['@ngtools/webpack']
                },

                {
                    test: /\.js$/,
                    loader: '@angular-devkit/build-optimizer/webpack-loader',
                    options: {
                        sourceMap: false
                    }
                }
            ]
        },
        plugins: [
            new UglifyJsPlugin({
                uglifyOptions: {
                    warnings: false,
                    ie8: false,
                    output: {
                        comments: false
                    }
                }
            })
        ]
    }),
    buildPath: function root(args) {
        var _root = path.resolve(__dirname);
        args = Array.prototype.slice.call(arguments, 0);
        return path.join.apply(path, [_root].concat(args));
    }
};

* webpack.config.common.js *

var HtmlWebpackPlugin = require('html-webpack-plugin');
var glob = require("glob");
var path = require('path');

module.exports = {
    entry: './src/main.ts',
    resolve: {
        extensions: ['.js', '.ts']
    },
    module: {
        rules: [
            {
                test: /\.html$/,
                loaders: ['html-loader']
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: "to-string-loader"
                    },
                    {
                        loader: "css-loader", // translates CSS into CommonJS
                        options: {
                            sourceMap: true
                        }
                    },
                    {
                        loader: "sass-loader", // compiles Sass to CSS
                        options: {
                            sourceMap: true,
                            includePaths: glob.sync(
                                path.join(__dirname, '**/node_modules/@mypackage/styles/src/abstracts')
                              ).map((dir) => path.dirname(dir)),
                            // includePaths: [path.resolve("node_modules/@mypackage")],
                            // includePaths: [
                            //     path.resolve('../node_modules')
                            // ]
                        }
                    }
                ]
            }

        ],
        exprContextCritical: false
    },
    plugins: [

        new HtmlWebpackPlugin({
            template: 'src/index.html'
        })
    ]
};

Версии использую для этого. "@ angular / compiler-cli": "7.2.15"
"uglifyjs-3-webpack-plugin": "1.2.4"
"@ angular-builders / custom-webpack": "7.4.3 "
" @ ngtools / webpack ":" 7.0.7 ",
" @ types / node ":" 8.9.5 "
" node-sass ":" 4.5.3 "
" sass-loader ":" 7.3.1 "
" to-string-loader ":" 1.1.5 "
" ts-node ":" 7.0.1 "
" typescript ":" 3.2. 4 "
" webpack ":" 4.29.0 "
" webpack-cli ":" 3.3.10 "
" webpack-merge ":" 4.2.2 "
И узел 8.9.5 с npm 5.5.1

Спасибо!


person Andres Ceron Moreno    schedule 24.01.2020    source источник


Ответы (1)


У меня была такая же проблема, и я решил ее sass-loader, применив следующее правило для scss webpack.config.common.js:

            {
                test: /\.component\.(css|sass|scss)$/,
                use: [
                    'to-string-loader',                  
                    'css-loader',
                    {
                        loader: 'sass-loader',
                        options: {
                            sassOptions: {
                                importer: url => {
                                    if (url.startsWith('@angular/')) {
                                        return {
                                            file: path.resolve(`./node_modules/${url}`),
                                        };
                                    }
                                    return null;
                                },
                            },
                        }
                    }
                ]
            }

Если у вас есть другая библиотека в node_module, которую вам нужно использовать, вы можете добавить еще один оператор else if:

Например, допустим, у меня есть пользовательская библиотека my-library в node_modules, и я хочу получить доступ к: node_modules/my-library/style.scss, поэтому мне нужно добавить следующий оператор else if:

       {
            test: /\.component\.(css|sass|scss)$/,
            use: [
                'to-string-loader',                  
                'css-loader',
                {
                    loader: 'sass-loader',
                    options: {
                        sassOptions: {
                            importer: url => {
                                if (url.startsWith('@angular/')) {
                                    return {
                                        file: path.resolve(`./node_modules/${url}`),
                                };
                                else if (url.startsWith('my-library/')) {
                                        return {
                                            file: path.resolve(`./node_modules/${url}`),
                                        };
                                    }
                                return null;
                            },
                        },
                    }
                }
            ]
        }

Учтите, что это была моя структура проекта:

node_modules
dist
config
  - webpack.common.js
  - webpack.dev.js
  - webpack.prod.js
  - webpack.test.js
src
  - app
    - app-routing.module.ts
    - app.component.html
    - app.component.scss
    - app.component.ts
    - app.module.ts
    - index.ts
  - index.html
  - main.browser.ts
  - polyfills.browser.ts
angular.json
package.json
postcss.config.js
tsconfig.json
tsconfig.webpack.json
webpack.config.js

Сообщите мне, работает ли это для вас.

person German Quinteros    schedule 24.01.2020
comment
Привет @ gquinteros93! Мне понравились ваши sassOptions, но для меня это не сработало. Если стоит упомянуть, до этой ошибки, о которой я упоминал здесь, я получил другую ошибку, которую я решил, выполнив npm link в моем локальном пакете и npm link packageName в папке проекта. Таким образом я избавился от этой первой проблемы (см. Последний комментарий к этой ссылке. [stackoverflow.com/questions/43037590/) Я не знаю, имеет ли это какое-то отношение к этому? Я перепробовал все возможные решения, но хорошего решения не было. Спасибо за помощь! - person Andres Ceron Moreno; 25.01.2020