如何使用npm和Django加载CSS静态文件的正确方式?

23

我想从我的node_modules目录加载静态CSS文件(例如Bootstrap),像这样:

{% load staticfiles %}
<link rel="stylesheet" href="{% static 'bootstrap/dist/css/bootstrap.min.css' %}" />
当我在STATICFILES_DIRS设置中添加.../node_modules/时,它可以正常工作。但是,它也会向我的/static/文件夹中添加大量的文件 - 大多数是前端不需要访问的devDependencies
如何最好地通过npm包含某些静态资源,而不将node_modules中的所有内容都包含在/static/文件夹中?
或者,包含这么多无关的文件是否可以,这是最佳解决方案?

1
这看起来很方便:https://github.com/whitespy/django-node-assets - guettli
4个回答

9
我所做的是以下内容:
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'),
)

这将只在我的静态文件夹中放置所需的文件。

谢谢 - 所以你可以在这里添加文件路径。我本来期望这会在存储的listdir方法中引发OSError:[Errno 20]不是目录。你的STATICFILES_STORAGE设置是什么?另外,你如何在模板中添加它们? - YPCrumble
抱歉,我确实犯了一个错误。我会改进答案。我不应该加载这些文件。 - Jostcrow
我明白了 - 但是这样的话,你的模板中每个文件都需要单独一行吗? - YPCrumble
据我所知,是的。 - Jostcrow

7
为了避免静态文件夹中引入许多未使用的文件,我使用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's 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's 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中,您可以将文件连接和压缩成一个文件。以下是我使用Blueimp的文件上传库的Gulpfile示例:

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

// Task 3: minify blueimp's 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/'))
}

谢谢!您能添加您的Django模板吗?您是在本地调用gulp并提交结果拼接的JS文件,还是将gulp作为构建过程的一部分来调用呢? - YPCrumble
@YPCrumble,我添加了Django模板。不,我不提交_vendor文件夹,因为它会在CI运行npm install时自动填充。出于同样的原因,我也不提交node_modules/。我只提交package.jsongulpfile.js - Benoit Blanchon

3

我个人认为,在node_modules(并复制到STATIC_ROOT)中存储这些额外的dev文件是可以的。如果您的node_modules文件夹很大,那么可能会有所不同,但是对于我的用例来说,将大小翻倍通常不是个大问题,并且不必在安装每个模块时都列出它们,这样很方便。

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

然后在您的模板中,执行以下操作:

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

如果文件夹的大小失控,出现冲突,或者有一个你真的不想要的库,Jostcrow的答案(或编写自定义静态文件查找器)可能是有意义的。此外,值得一试的是尝试将所有内容捆绑在一起。如果所有东西都存在于捆绑的JS/CSS文件中,只需将这些文件webpack到您选择的应用程序中即可解决整个问题。

0

自从我的上一个回答以来,我改变了做事的方式。现在,我使用django-npm,这是一个极其简单的包,允许您从node_modules/中挑选要导入的文件。 作为比较,以下是我如何实现与先前响应相同的结果:

package.json

{
  "dependencies": {
    "bootstrap": "^4.3.1",
    "jquery": "^3.4.1"
  }
}

my_project/settings.py

STATICFILES_FINDERS = (
  ...
  'npm.finders.NpmFinder',  # see django-npm's installation instructions
)

NPM_STATIC_FILES_PREFIX = 'node_modules'
NPM_FILE_PATTERNS = {
    'bootstrap': [
        'dist/js/bootstrap.bundle.min.*',
    ],
    'jquery': [
        'dist/jquery.min.*',
    ],
}

关于拼接和压缩呢?

我使用 django-compressordjango-sass-processor


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接