Сборка Webpack 4 с Angular 7 дает проблему с загрузчиком sass при попытке доступа к node_modules - PullRequest
1 голос
/ 24 января 2020

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

В Angular 4 он отлично работал с пользовательским конструктором веб-пакетов, но обновление до v7 имеет свои сложности. Также стоит упомянуть, что попытка сборки без каких-либо @imports в s css для узлов 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"; Родительская таблица стилей: stdin в / Path / to / project (строка 4, столбец 1)

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

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

Файлы конфигурации 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"
"uglify js -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 "
" typcript ":" 3.2.4 "
" webpack ":" 4.29.0 "
" webpack-cli ":" 3.3.10 "
" webpack-merge ":" 4.2.2 "
И узел 8.9.5 с npm 5.5.1

Спасибо!

1 Ответ

0 голосов
/ 24 января 2020

У меня была та же проблема, и я решил ее с помощью 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

Дайте мне знать, если это работает для вас.

...