Gatsby主题使用gatsby-source-filesystem无法从站点目录拉取文件
问题根因
__dirname是Node.js内置全局变量,永远返回当前执行代码所属文件的绝对目录路径,不会因为代码被作为主题/依赖引入,就自动指向宿主项目目录。
你观察到的gatsby-plugin-page-creator“反常”表现属于认知偏差:Gatsby默认就会自动扫描启动命令所在目录下的src/pages生成页面,和你在主题里配置的path.join(__dirname, "src/pages")无关——你写的这条配置实际只会扫描主题包自身的src/pages目录,宿主项目的页面是Gatsby默认规则扫描识别的,并非这条配置的效果。
你在gatsby-node.js中写的目录创建逻辑已经直接印证了__dirname的实际指向:执行后在主题目录生成images文件夹,完全符合Node.js原生行为,不属于插件bug。
修复方案
要实现主题同时读取自身默认资源、宿主项目自定义资源的效果,不要硬编码__dirname拼接路径,按以下方式调整:
- 改造主题的
gatsby-config.js,支持自定义资源路径,默认通过process.cwd()获取宿主项目根目录(即执行Gatsby启动命令的工作目录),同时保留主题自身默认资源的扫描规则:
const path = require("path") module.exports = (themeOptions = {}) => { // 宿主项目图片目录,支持用户通过主题配置自定义路径,默认取宿主根目录下的images文件夹 const siteImagesPath = themeOptions.imagesPath || path.join(process.cwd(), "images") // 主题自带默认图片目录 const themeDefaultImagesPath = path.join(__dirname, "images") // 宿主项目页面目录 const sitePagesPath = path.join(process.cwd(), "src/pages") // 主题自带默认页面目录 const themePagesPath = path.join(__dirname, "src/pages") return { plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `site-images`, path: siteImagesPath, }, }, { resolve: `gatsby-source-filesystem`, options: { name: `theme-default-images`, path: themeDefaultImagesPath, }, }, { resolve: "gatsby-plugin-page-creator", options: { path: sitePagesPath, }, }, { resolve: "gatsby-plugin-page-creator", options: { path: themePagesPath, }, } ] } }
- 修正
gatsby-node.js中的目录初始化逻辑,在宿主项目对应目录不存在时自动创建,不要在主题包目录下生成文件夹:
const fs = require("fs") const path = require("path") exports.onPreBootstrap = ({ reporter }, themeOptions = {}) => { const contentPath = themeOptions.imagesPath || path.join(process.cwd(), "images") if (!fs.existsSync(contentPath)) { reporter.info(`初始化图片资源目录: ${contentPath}`) fs.mkdirSync(contentPath, { recursive: true }) } }
验证方式
调整完成后:
- 存放在宿主项目
example.com/images目录下的图片会被gatsby-source-filesystem正常识别 - 主题自带的默认图片资源也会被正常收录,不会因为用户未创建自定义图片目录报错
- 宿主项目
src/pages、主题自带页面目录下的页面都会被正常创建 - 访问GraphQL playground执行文件查询,可以同时返回两个来源的文件节点
注意:所有Node.js依赖、主题开发场景下,不要依赖
__dirname指向宿主项目,要获取启动命令对应的项目根目录统一使用process.cwd()。
内容的提问来源于stack exchange,提问作者Alexander Hörl
相关产品推荐
相关产品推荐

