Как импортировать CSS из node_modules в приложение webpack angular2

#css #angular #typescript #npm #webpack

#css #angular #typescript #npm #webpack

Вопрос:

Допустим, мы начинаем со следующего стартового пакета: https://github.com/angularclass/angular2-webpack-starter

После npm install и npm run start все работает нормально.

Я хочу добавить внешний модуль css, например, css bootstrap 4 (и только css). (Я знаю, что в bootstrap есть загрузчик начальной загрузки, но теперь я прошу общего решения, поэтому, пожалуйста, подумайте о bootstrap 4 здесь, поскольку это может быть любой другой модуль css, доступный через npm).

Я устанавливаю bootstrap через npm: npm install bootstrap@4.0.0-alpha.4 --save

Сначала я подумал, что достаточно добавить import 'bootstrap/dist/css/bootstrap.css'; в файл vendor.browser.ts.

Но это не так.

Что я должен сделать, чтобы получить правильное решение?

Решения, о которых я НЕ прошу:

  1. «Скопируйте внешний модуль css в папку assets и используйте его оттуда»
    • Я ищу решение, которое работает вместе с пакетом npm.
  2. «Использовать загрузчик для webpack»
    • Как я описал выше, я ищу общее решение, bootstrap здесь только пример.
  3. «Использовать другой стек»
    • Я ищу решение в точном стартовом пакете, о котором я упоминал выше.

Комментарии:

1. Вы получаете какую-либо ошибку?

2. Это официально лучшая тема SO, в которой я когда-либо участвовал. Звездный вопрос и два столь же звездных ответа. Спасибо всем.

Ответ №1:

Это возможно с помощью @import '~bootstrap/dist/css/bootstrap.css'; файла styles.css. (Обратите внимание на ~)

Редактировать: Как это работает — ‘~’ — это псевдоним, установленный в конфигурации webpack, указывающий на папку assets… все просто..

Редактирование 2: Пример настройки webpack с псевдонимом ‘~’ … это должно быть в файле конфигурации webpack (обычно webpack.config.js )…

 // look for the "resolve" property and add the following...
// you might need to require the asset like '~/bootsrap/...'
resolve: {
  alias: {
    '~': path.resolve('./node_modules')
  }
} 

Комментарии:

1. Это сработало для меня, и мне очень нравится идея сохранения моих файлов css, поэтому я не хотел использовать ViewEncapsulation. нет сделки. Но как это работает?

2. Насколько я знаю, это что-то в компиляторе, но поскольку я не эксперт, я оставлю это кому-то, кто знает лучше, чтобы объяснить, как это работает…

3. Я попробовал это, но получил сообщение об ошибке: GET localhost:55490/~bootstrap/css/bootstrap.min.css 404 (Не найден)

4. Для тех, кто хочет понять, как это работает, вот хорошее чтение blog.angularindepth.com /…

5. Раньше это не работало в Angular 6, но работает для Angular 7. Однако я не вижу в журнале изменений ничего, что объясняет, почему. Кто-нибудь знает?

Ответ №2:

Вы не сможете импортировать какой-либо css в свой файл vendors, используя этот стек, без внесения некоторых изменений.

Почему? Ну, потому что эта строка:

 import 'bootstrap/dist/css/bootstrap.css';
 

Это только импорт вашего css в виде строки, когда на самом деле вам нужен css вашего поставщика в теге стиля. Если вы проверите config/webpack.commons.js , вы найдете это правило:

  {
   test: /.css$/,
   loaders: ['to-string-loader', 'css-loader']
 },
 

Это правило позволяет вашим компонентам импортировать файлы css, в основном это:

 @Component({
  selector: 'app',
  encapsulation: ViewEncapsulation.None,
  styleUrls: [
    './app.component.css' // this why you import css as string
  ],
 

В AppComponent нет инкапсуляции из-за этой строки encapsulation: ViewEncapsulation.None, , что означает, что любые правила css будут применяться глобально к вашему приложению. Таким образом, вы можете импортировать стили начальной загрузки в свой компонент приложения:

 @Component({
  selector: 'app',
  encapsulation: ViewEncapsulation.None,
  styleUrls: [
    './app.component.css',
    '../../node_modules/bootstrap/dist/css/bootstrap.css'
  ],
 

Но если вы настаиваете на импорте в свой vendor.ts , вам нужно будет установить новый загрузчик, npm i style-loader --save-dev это позволит webpack вводить css на вашу страницу. Затем вам нужно создать конкретное правило на вашем webpack.common.js и измените существующий:

  { //this rule will only be used for any vendors
   test: /.css$/,
   loaders: ['style-loader', 'css-loader'],
   include: [/node_modules/]
 },
 {
   test: /.css$/,
   loaders: ['to-string-loader', 'css-loader'],
   exclude: [/node_modules/] //add this line so we ignore css coming from node_modules
 },
 

Первое правило будет применяться только при попытке импортировать css из любого пакета внутри node_modules второе правило будет применяться к любому css, который вы импортируете извне node_modules

Комментарии:

1. Спасибо, чувак, это своего рода идеальный ответ, который я искал. Оба решения работают хорошо. Одна вещь, которую я не знал, это то, что можно настроить таргетинг на node_modules из styleUrls. Это тоже предпочтительная вещь?

2. Нет правильного или неправильного, либо они действительны, но если в будущем вы планируете размещать свой vendor.css в отдельном файле, тогда последний вариант лучше.

3. обратите внимание, что angular2-webpack-starter уже имеет загрузчик стилей в своем package.json (что означает, что для его использования в этом примере не требуется дополнительная установка npm)

4. @Burnee верно, но это бот, который используется где угодно, поэтому они могут удалить его в будущем. Так что оставлю в ответе, на всякий случай, для будущих читателей.

5. Как заставить мое угловое приложение обрабатывать импорт установленной библиотеки @import "~dist/3rd_party_lib/blabla.css как node_modules/dist/3rd_party_lib/blabla.css , а не как https://localhost:4200/~/dist/3rd_party_lib/blabla.css ?

Ответ №3:

Итак, вот способ импортировать различные CSS файлы, используя тот angular-cli , который я нахожу наиболее удобным.

В принципе, вы можете ссылаться на CSS файлы (порядок важен, если вы будете переопределять их) в конфигурации и angular-cli позаботитесь обо всем остальном. Например, вы можете захотеть включить пару стилей из node-modules, что можно сделать следующим образом:

 "styles": [
    "../node_modules/font-awesome/css/font-awesome.min.css",
    "../node_modules/primeng/resources/primeng.min.css",
    "styles.css"
  ]
 

Пример полной конфигурации может выглядеть следующим образом:

.angular-cli.json

 {
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "my-angular-app"
  },
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": [
        "../node_modules/font-awesome/css/font-awesome.min.css",
        "../node_modules/primeng/resources/primeng.min.css",
        "styles.css"
      ],
      "scripts": [],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    }
  ],
  "e2e": {
    "protractor": {
      "config": "./protractor.conf.js"
    }
  },
  "lint": [
    {
      "project": "src/tsconfig.app.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "src/tsconfig.spec.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "e2e/tsconfig.e2e.json",
      "exclude": "**/node_modules/**"
    }
  ],
  "test": {
    "karma": {
      "config": "./karma.conf.js"
    }
  },
  "defaults": {
    "styleExt": "scss",
    "component": {}
  }
}