Каков правильный способ загрузки статических файлов CSS с использованием npm и Django?

Я хочу загрузить мои статические файлы css (например, Bootstrap) из моего каталога node_modules, например:

{% load staticfiles %}
<link rel="stylesheet" href="{% static 'bootstrap/dist/css/bootstrap.min.css' %}" />

Когда я помещаю .../node_modules/ в настройку STATICFILES_DIRS, это работает. Однако он также добавляет огромное количество файлов в мою папку /static/ - в основном devDependencies, для которой мне не нужен доступ к интерфейсу.

Какова наилучшая практика включения определенных статических активов через npm, но не включая все из node_modules в моей папке /static/?

Или, хорошо ли включить так много посторонних файлов и что лучшее решение?

Ответ 1

Я делаю следующее:

STATICFILES_DIRS = (
    os.path.join(DJANGO_PROJECT_DIR, 'static'),
    os.path.join(ROOT_DIR, 'node_modules', 'd3', 'build'),
    os.path.join(ROOT_DIR, 'node_modules', 'c3'),
)

В моей статической папке будут помещены только нужные файлы.

Ответ 2

Я лично считаю, что все эти посторонние файлы разработчиков живут в node_modules (и дублируются в STATIC_ROOT). Ваш пробег может отличаться, если ваша папка node_modules является гигантской, но удвоение размера обычно не является большой проблемой для моих вариантов использования, и удобнее не указывать каждый модуль в STATICFILES_DIRS, когда я их устанавливаю.

STATICFILES_DIRS = (
    ...
    os.path.join(BASE_DIR, 'node_modules'),
    ...
)

Затем в ваших шаблонах выполните:

<script src='{% static 'bootstrap/dist/css/bootstrap.min.css' %}'></script>

Если папка когда-либо выходила из рук по размерам, если вы столкнулись с конфликтами или если была библиотека, которую вы действительно не хотели обслуживать, то ответ Jostcrow (или написание пользовательского статического файла поиска) мог бы иметь смысл.

Кроме того, может быть стоит посмотреть на попытку собрать все вместе. Если все ваши вещи находятся в комплекте с JS/CSS файлами, вся проблема решена просто путем веб-загрузки этих файлов в ваше приложение по выбору.

Ответ 3

Чтобы не импортировать много неиспользуемых файлов в статическую папку, я копирую нужные элементы с помощью сценария Gulp. Я использую сценарий NPM для вызова Gulp после установки пакетов, поэтому он не влияет на мой ежедневный рабочий процесс.

package.json:

{
  "dependencies": {
    "bootstrap": "^4.3.1",
    "gulp": "^4.0.2",
    "jquery": "^3.4.1"
  },
  "scripts": {
    "install": "gulp"
  }
}

gulpfile.js

const { series, src, dest } = require('gulp');

// Task 1: copy bootstap assets to /_vendor/
function bootstrap() {
  const files = [
    'node_modules/bootstrap/dist/css/bootstrap.min.css',
    'node_modules/bootstrap/dist/js/bootstrap.min.js'
  ]
  return src(files).pipe(dest('_vendor'))
}

// Task 2: copy jquery assets to /_vendor/
function jquery() {
  const files = [
    'node_modules/jquery/dist/jquery.min.js'
  ]
  return src(files).pipe(dest('_vendor'))
}

exports.default = series(bootstrap, jquery)

my_project/settings.py:

STATICFILES_DIRS = [
    str(BASE_DIR / '_vendor'),  # populated by gulp
]

Шаблон Django:

{% load staticfiles %}
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}" />

Бонус 🎉

В Gulpfile вы можете объединять и минимизировать файлы. Например, вот моя библиотека загрузки файлов Gulpfile для Blueimp:

const uglify = require('gulp-uglify');
const concat = require('gulp-concat');

// Task 3: minify blueimp assets and save to /_vendor/
function blueimp() {
  const files = [
    'node_modules/blueimp-file-upload/js/vendor/jquery.ui.widget.js',
    'node_modules/blueimp-file-upload/js/jquery.iframe-transport.js',
    'node_modules/blueimp-file-upload/js/jquery.fileupload.js'
  ]
  return src(files).pipe(uglify())
                   .pipe(concat('jquery.fileupload.min.js'))
                   .pipe(dest('_vendor/'))
}