使用Laravel Mix合并多个文件

23

我目前正在深入学习Laravel Mix,到目前为止,虽然我完全理解Laravel Mix是什么以及它的工作原理,但我正在尝试更多地了解常见做法和“如何”...

例如,考虑以下文件结构:

/resources/assets/js/app.js (all global functions)
/resources/assets/js/index/index.js (functions specific to index.js)
/resources/assets/js/about/about.js (functions specific to about.js)
/resources/assets/js/contact/contact.js (functions specific to contact.js)

现在,理想情况下,我希望以下内容以以下方式合并和压缩:

/public/js/index/index-some_hash.js (including app.js)
/public/js/about/about-some_hash.js (including app.js)
/public/js/contact/contact-some_hash.js (including app.js)

据我所知,实现这一目标的方法大概是这样的:

// Index
mix.js([
    'resources/assets/js/app.js',
    'resources/assets/js/index/index.js'
], 'public/js/index/index.js').version();

// About
mix.js([
    'resources/assets/js/app.js',
    'resources/assets/js/about/about.js'
], 'public/js/about/about.js').version();

// Contact
mix.js([
    'resources/assets/js/app.js',
    'resources/assets/js/contact/contact.js'
], 'public/js/contact/contact.js').version();

我的问题

简单地说,我想知道上面的方法是否是我尝试做到的正确方法?是否有更好的方法或更常见的方法来实现这个目标呢?

如果上述结构是错误的,并且有其他方式可以组合我的文件,请分享您的知识。然而,除非有非常好的理由,否则我希望避免以下情况:

  • 为每个页面提供两个单独的文件,即app.min.js和index.min.js。 这需要每页两次查找,理想情况下应该尽可能少
  • 向网站上的所有页面提供相同的文件。向不需要使用它的页面提供代码是一种资源浪费,无论如何都要缓存...

一个想法...

我注意到在JS文件中有一行代码:require('./bootstrap');。请原谅我落伍了,但我从未在JavaScript中看到过这样的写法(我假设它来自node.js)。话虽如此,显然它只是将bootstrap.js文件作为依赖项加载到特定文件中。因此,考虑到这一点,以下解决方案是否更好:

about.js

require('./app'); // Include global functions

// Do some magic here specifically for the 'about' page...

webpack.mix.js:

mix.js(['resources/assets/js/*/*.js'); // For all pages
如果这是一个更好的解决方案,那么如何使用SASS包含文件?上述方法是否有改进的空间?

如果这是一个更好的解决方案,那么如何使用SASS包含文件?上述方法是否有改进的空间?


1
我认为Sass有一个import语句,它的行为类似于JavaScript中的require - Cerlin
@CerlinBoss 很好,这是否意味着我的“可能”的解决方案比第一个更好? - Ben Carey
我唯一能看到的区别就是一个精简的 mix 文件。 - Cerlin
第二个方案可行。使用 require 是 Node.js 模块加载的方式。webpack 可能会为 require 方法添加一个 poly-fill,或将代码附加到所有单独的 .js 文件中(我不确定 webpack 实际使用哪种方法)。将第二个解决方案称为“更好”的方案完全取决于每个人的个人偏好,这是主观的。 - Cerlin
我正在努力学习使用Laravel Mix的最佳实践。 Laravel Mix的最佳实践已经在文档中提到了。我认为你是在寻找不同的javascript实现方式。目前,您拥有所有浏览器都能理解的vanila js,因此我建议您执行**这个**而不是以不同的样式重新实现您的javascript。 - Cerlin
显示剩余2条评论
1个回答

35

这里有三个主要的因素需要考虑(它们并不都同等重要):

  • 大小 - 所需资源占用的空间以及正在下载的文件的文件大小。
  • 请求数量 - 页面中加载了多少文件。
  • 浏览器缓存 - 文件将从缓存中获取,而不是从服务器获取。

在您的特定情况下,这将取决于您的app.js文件本身的大小,没有来自app.js代码的页面特定文件的大小,您有多少个页面特定文件,以及您是否在不同的文件中使用相同的资源,例如在不同的文件中要求相同的软件包。


一个文件

如果您的页面特定文件相当小,则可以将它们直接包含在您的主app.js文件中:

require('./index/index')
require('./about/about')
//etc

webpack.mix.js:

.js('resources/assets/js/app.js', 'public/js')

这意味着您只需在服务器上存储一个已编译的文件,每个页面加载仅发起一次JavaScript请求,并且应该在整个站点的所有后续页面加载期间被缓存。


主文件和特定页面文件

如果您有大量特定于页面的文件或您的页面特定文件不太小,则建议独立编译app.js而不是与页面特定文件一起编译。不要忘记将此方法的结果与“单一文件”方法进行比较,因为“单一文件”方法可能仍然更有效。

webpack.mix.js

.js('resources/assets/js/app.js', 'public/js')
.js('resources/assets/js/index/index.js', 'public/js/index')
.js('resources/assets/js/about/about.js', 'public/js/about')

这意味着你的主要代码 (app.js) 的大部分仍将被缓存,而且仅针对页面特定的代码仅进行一次请求 (然后应该为该页面的每个后续加载进行缓存)。

请注意,如果您在app.js文件和页面特定文件中都需要包,则它们不会在两者之间共享,因此这将增加这些请求的总体大小。可添加到window对象中的包 (例如 jQuery) 应仅包含在您的app.js文件中。

解决这个问题的一种方法是使用Vendor Extraction (Laravel Mix文档):

.extract(['jquery'])

这将产生两个额外的文件,你需要在你的HTML中包含它们:

<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script> 

一个主文件和几个特定页面的文件

如果你有一个或两个相当大但其余不大的特定页面文件,你可以将大部分特定页面文件编译到app.js中,并将较大的文件编译为它们自己的文件。


所有特定页面的文件

只有当所有特定页面文件都相当大、你的app.js文件不是很大、并且特定页面文件中的代码/逻辑无法重构以在不同文件之间共享时,才建议采用这种方法。

这种方式类似于你问题中的示例,但不同的是:

webpack.mix.js

mix.js([
    'resources/assets/js/app.js',
    'resources/assets/js/index/index.js'
], 'public/js/index/index.js').version();

您将拥有:

resources/assets/js/index/index.js

require('../app.js')

//rest of file

webpack.mix.js

->

webpack.mix.js

mix.js('resources/assets/js/index/index.js', 'public/js/index/index.js').version();

我不会直接使用这种方法,只有在极少数情况下才会是最有效的方法。


总结

我通常会优先考虑单文件的方法,然后再进行优化(除非在开发期间出现了明显的问题),因为过早地进行优化可能会导致代码质量变差和难以维护。

这篇文章对您也可能有用:https://medium.com/@asyncmax/the-right-way-to-bundle-your-assets-for-faster-sites-over-http-2-437c37efe3ff


一个JS文件会不会引起问题,因为JS需要按顺序加载? - FabricioG
@FabricioG 我从来没有遇到过这个问题。 - Rwd

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