ExtractTextPlugin в веб-пакете для Angular 2

У меня есть рабочая конфигурация для webpack с Angular, так что файлы scss вставляются в bundle.js

{
  test: /\.scss$/,
  use: ['raw-loader', 'resolve-url-loader', 'sass-loader?sourceMap']
}

но вместо этого я хочу получить один файл css со всеми scss в приложении, поэтому я использую ExtractTextPlugin, как это

{
  test: /\.scss$/,
  use: ExtractTextPlugin.extract({
    fallback: ['raw-loader', 'resolve-url-loader', 'sass-loader?sourceMap'],
    use: ['resolve-url-loader', 'sass-loader?sourceMap']
  })
}

Теперь я не использую «raw-loader», потому что я понимаю, что файлы не нужно вставлять в bundle.js, но я получаю сообщение об ошибке при компиляции.

ERROR in ./~/resolve-url-loader!./~/sass-loader/lib/loader.js?sourceMap!./app/app.component.scss
    Module parse failed: /Users/david/Documents/work/my-angular-seed/node_modules/resolve-url-loader/index.js!/Users/david/Documents/work/my-angular-seed/node_
modules/sass-loader/lib/loader.js?sourceMap!/Users/david/Documents/work/my-angular-seed/app/app.component.scss Unexpected token (1:0)
    You may need an appropriate loader to handle this file type.
    | .app {
    |   border: 1px solid red;
    | }

Если я использую необработанный загрузчик, сборка идет нормально, но затем я получаю сообщение об ошибке при загрузке index.html.

Uncaught Error: Expected 'styles' to be an array of strings.

Кто-нибудь знает, как это исправить и почему это происходит? Спасибо!

РЕДАКТИРОВАТЬ

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

Если я использую эту конфигурацию

{
  test: /\.scss$/,
  use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: ['css-loader', 'sass-loader']
  })
}

создается app.css, так что все хорошо. Но затем, если я проверю bundle.js, компонент был преобразован в этот

AppComponent = __decorate([
    core_1.Component({
        selector: 'app-root',
        styles: [__webpack_require__(23)],
        template: "\n    <div class=\"app\">\n      Hello!\n    </div>\n  "
    })
], AppComponent);

И если я проверю модуль 23, я увижу, что он пустой

/* 23 */
/***/ (function(module, exports) {

// removed by extract-text-webpack-plugin

/***/ }),

Итак, я предполагаю, что это то, на что жалуется angular, стили - это пустой массив. Я думаю, что здесь нужно полностью удалить тег стилей, так как css используется как внешний отдельный файл, верно? есть ли способ исправить это?


person David    schedule 03.03.2017    source источник


Ответы (1)


Вы можете использовать css-loader, который обычно используется вместо raw-loader для CSS. И fallback — это загрузчик, который используется, когда CSS не будет извлечен (как указано в извлечь параметры). Я не могу придумать никакого другого применения, кроме style-loader, которое вставляло бы CSS в тег <style>. Загрузчики, которые вы указываете в use, по-прежнему применяются до этого, поэтому использование raw-loader на самом деле не будет иметь никакого эффекта.

Вы должны изменить правило .scss на это обычное (аналогично примеру в Извлечение Sass):

{
  test: /\.scss$/,
  use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: ['css-loader', 'resolve-url-loader', 'sass-loader?sourceMap']
  })
}

Если вы не хотите использовать style-loader в качестве запасного варианта, вы можете оставить его, CSS все равно будет в комплекте, если он не извлечен, просто не введен в тег <style>, но это, вероятно, вам не поможет.

person Michael Jungo    schedule 03.03.2017
comment
Я все еще получаю сообщение об ошибкеUncaught Error: Expected 'styles' to be an array of strings., поэтому app.css генерируется, но приложение не работает. - person David; 04.03.2017
comment
Как вы их используете? Если он находится в @Component, он будет styles: [css.app, css.other] после импорта, например import css from './app.component.scss'. Это добавит к нему классы app и other. - person Michael Jungo; 04.03.2017
comment
Я обновил свой вопрос, добавив немного больше информации; на самом деле это не имеет значения в окончательном пакете.js, использую ли я resolve-url-loader или нет, результат тот же - person David; 04.03.2017
comment
Первоисточник является релевантным, а не сгенерированным. В любом случае, похоже, что вы передаете весь импортированный css, который представляет собой объект с классами, сопоставленными с сгенерированными хэш-именами для каждого класса css. И использовать имя класса в шаблоне не получится, классы заменяются хешами (так работают модули css) - person Michael Jungo; 04.03.2017
comment
Я потерялся здесь. В моем index.html у меня есть <link href="app.css" rel="stylesheet"></head>, а app.css — это пакет со всеми css в приложении, разве этого не должно быть достаточно? Я понимаю, что для разработки имеет смысл иметь отдельные файлы scss для компонентов, но после сборки, если у меня все стили уже собраны в файле и этот файл импортирован в основной index.html, не должны все стили удалить импорт из компонентов? - person David; 04.03.2017
comment
Извините, я что-то перепутал, вы не используете модули CSS, так что забудьте, что я сказал об их импорте. Вам не нужно указывать какие-либо стили, так как вы уже добавили нужные классы в свой шаблон. Но вам все равно нужно его импортировать (чтобы веб-пакет знал, как его обработать), просто: import './app.component.scss'. Так что оставьте styles полностью. - person Michael Jungo; 04.03.2017
comment
Мне это кажется неправильным, мне не нужно изменять файлы src для использования webpack, systemjs или любого другого. - person David; 04.03.2017
comment
Если вы хотите, чтобы CSS обрабатывался wepack, вам необходимо импортировать его. Вам следует прочитать Концепции webpack, особенно раздел загрузчиков и Как CSS используется в webpack. - person Michael Jungo; 04.03.2017