在 Nuxt 中加载 JSON 时如何从摇树和代码拆分中受益?
Posted
技术标签:
【中文标题】在 Nuxt 中加载 JSON 时如何从摇树和代码拆分中受益?【英文标题】:How to benefit from tree-shaking and code-splitting while loading JSON in Nuxt? 【发布时间】:2022-01-22 12:39:34 【问题描述】:我有一个 nuxt 应用程序,其中有很多帖子。我最近重构了这个项目,我不会再generate
所有帖子了,因为这样做会花费太多时间。
相反,我有一个页面,可以通过 url 查询获取匹配的帖子内容:
www.mypage.com/posts/?post=my-post-slug
因为内容位于静态 json 文件中,例如:
/static/data/posts/my-post-slug.json
/static/data/posts/my-post-slug_2.json
/static/data/posts/my-post-slug_3.json
/static/data/posts/my-post-slug_n.json
我看了帖子https://github.com/nuxt/nuxt.js/issues/123 关于如何以最佳方式加载 json。
我决定在 fetch() 钩子中做这样的事情:
// ... simplified code
async fetch()
let postSlug = this.$route.query.post
const post = this.$axios
.get(`/posts/posts.de.$postSlug.json`)
.then((data) =>
return data?.data
)
.catch((error) =>
console.error('error: ', error)
const code = parseInt(error.response && error.response.status)
if (code === 404)
this.$nuxt.error( statusCode: 404, message: 'Post not found' )
)
this.activePost = post?.items?.[0] || false
如前所述,我不会生成实际的帖子,但会在我的 sitemap.xml 中生成所有帖子网址。
在analyze 模式下运行生成时,我现在有一个 huuuuge 包大小 (app.js),但我不明白为什么...
-> 查看附件图片。 (注意:app.js
有 34MB 的荒谬大小!!!!!!????)
-
我不明白为什么我所有的 post json 都出现在 bundle 的 static 和 dist 部分???
我完全不明白他们为什么会出现在那里。我希望它们仅位于静态文件夹中,但不包含在应用程序包中。
(您可以看到其中包含
events.bundle.de.json
之类的文件。例如,我需要这些文件来获取所有帖子的列表。我也仅在我的 fetch 挂钩中执行此操作。
如果有人能指出为什么包含这些文件(两次),我会非常高兴!
【问题讨论】:
我意识到当我删除 dist 文件夹时,我最终得到了一半的大小。那里的数据是我重构之前的一些剩余数据。我还意识到,无论我将什么 json 放入静态文件夹,它总是会出现在 app.js 中——即使它不需要/导入或以任何其他方式使用......(这对我来说没有意义吗? !?) 【参考方案1】:这些文件没有“两次”包含。你需要它们,所以你在本地的 static
文件夹中拥有它们。
同时,如果您不希望/不需要将它们公开暴露并受益于代码拆分得益于 Webpack,您可能应该将它们放在您的 src
目录中,正如您链接的帖子中所解释的那样(即使是 2017 年的也仍然有效!)。
在这里,由于您正在进行 axios 调用并使用 target: 'static'
,即使没有 JS,它也会将您的整个工作捆绑在一起,并且它会提前完成。所以,为了拥有所有的可能性,我认为它包含了所有的最终捆绑包。
如果您只想加载需要的内容而不发送大的static
目录,您应该动态导入它们。您可以使用dynamic import:通过传递实际的postSlug
仅加载所需的JSON。
PS:风格方面,更喜欢使用async/await
(.then
已弃用),也可能使用$axios.$get
。
【讨论】:
非常感谢您的意见。我可以部分理解你所说的,但有些事情对我来说没有意义。与此同时,我已经按照您的建议进行了操作:我按照此处 (github.com/nuxt/nuxt.js/issues/123#issuecomment-272246782) 和您的回答中的建议动态导入数据。这可行,但是当我生成应用程序时,我仍然会得到一个包含所有 events.jsons 的 app.js,尽管我将它们移出static
文件夹。
我不明白的是:如果我不生成实际的事件页面和帖子页面,但只想在客户端上加载这些数据(有点懒惰,而不是完全静态不再),那么为什么这甚至出现在我的 app.js 中。 app.js 应该只包含一些全局数据和一些页面,这应该足以运行应用程序等 - 只有在我想要导入 jsons 之后,绝对不必出现在包中......?我可能仍然误解了一些事情......
看来 webpack 只是贪婪地抓取 json 文件并将其放入我的包中。如果我在我的项目根/random-folder/folder-containing-jsons/...
中创建一个随机文件夹并将我所有的 json 放入该文件夹中,那么整个数据仍然出现在我捆绑的 app.js 中......我想我需要特别告诉 webpack 不要捆绑那个文件夹。 (但是如何?!?)要在客户端上实际导入它,我想我必须将它放回静态文件夹中......
@Merc 最后,webpack 分析器会给你所有的可能性。它将显示所有这些,因为它们可以在某个时候导入,webpack 分析器在显示所有块时不是动态的(那里没有运行时延迟加载)。要检查这一点,您更适合加载您的应用程序并跟踪加载的内容,这要归功于您的 devtools 的 Network 选项卡。【参考方案2】:
虽然我认为@kissu 的回答是在标题中回答了我的问题,但这并不是我的问题的解决方案。为了完整起见,我将发布经过长时间调试后发现的内容。我仍然不太明白为什么会发生这种情况,但也许有人也可以对此发表评论:
在我的 nuxt 项目中,我使用了一个实用程序文件 getData.js
,我将其中的一个函数 getDataServer
导入到我的一个 vuex 存储模块中。
// vuex store module: store/data.js
import getPreviewData from '~/api/getData'
代码如下所示:
// getData.js
// Get static JSON file (e.g. basic.de.json or posts.de.1.json)
export function getDataServer(fileProps)
return require(`~/$fileProps.path$fileProps.name.$fileProps.lang$
fileProps.page ? `.$fileProps.page` : ''
.json`)
只有通过导入,甚至不通过执行该功能,webpack 才会将它可以在我的根文件夹中找到的每个 .json
文件捆绑到我的 app.js 中。
这就是为什么我的包中出现了一个 dist 文件夹,如果没有删除的话。 (我在最初的问题中谈到了这一点,其中包含了两次内容)。
我什至创建了额外的文件夹和 .json 文件来查看,无论如何它们都被捆绑了。
只有在从我的项目中删除 getData.js
之后,我的包才变得干净。
我了解使用require
命令,webpack 不能 tree-shake 东西,所以我本以为某些代码拆分功能不起作用,但我没想到的是这段代码会 自动获取我文件夹中的每个.json
...
有谁知道为什么导入该函数会以充当所有 .json 通配符的方式执行它? 对我来说仍然没有任何意义。
感谢和欢呼。
【讨论】:
require
是在 Node.js 中导入东西的旧方法。 import
在 ES 模块和 v2 以上的 Webpack 结合使用时启用 tree-shaking。如果你需要一个包,你会加载它的 100%,即使你只使用一小段代码。如果你 import properly 和 ES 模块,你可以只选择正在使用的代码,感谢 Webpack/Rollup/etc 对导出的代码进行了一些分析。摇树和代码拆分是相同的“import
俱乐部福利”的一部分。在现代应用程序中,您应该放弃 require
以支持 import
。
是的,我知道这一点。谢谢你再次总结。我不明白的是:我从未执行过使用require
的函数,它也不知道require
是哪个文件,因为实际路径取决于某些函数参数(如路径和名称)。那么,您如何解释这样一个事实,即仅通过导入使用 require
的函数,我最终会得到一个捆绑包,其中需要所有 jsons 并因此捆绑在一起?这对我来说仍然没有意义......
我猜是因为它不知道它在使用什么,并且没有分析实际导出的代码,它只是将它全部导入。 require
本质上是相当愚蠢的,同步代码,带来整个代码等等......不是专家,但我只知道现在,你可能永远不应该再使用 require
,特别是因为 Node 环境现在也支持它(在我的意思是服务器)。以上是关于在 Nuxt 中加载 JSON 时如何从摇树和代码拆分中受益?的主要内容,如果未能解决你的问题,请参考以下文章