使用 Laravel Mix 合并多个文件

Posted

技术标签:

【中文标题】使用 Laravel Mix 合并多个文件【英文标题】:Combining Multiple Files with Laravel Mix 【发布时间】:2017-07-26 02:46:50 【问题描述】:

我目前正在深入研究 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 有 import 声明,其行为类似于 javascript 中的 require @CerlinBoss Perfect,这是否意味着我的“可能”解决方案比第一个更好? 我能看到的唯一区别是一个纤细的mix 文件。 @CerlinBoss 好的,我的意思是,第二个解决方案会起作用吗?您会建议这样做吗?我正在尝试了解使用 Laravel Mix 的最佳实践。我在网上搜索过,虽然我完全了​​解 Laravel Mix 是什么,但我想了解如何最好地使用它...... 第二种解决方案将起作用。使用require 是nodejs 的模块加载方式。 webpack 可以为 require 方法添加一个 poly-fill 或将 app.js 中的代码附加到所有单独的 .js 文件中(我不确定 webpack 实际使用哪种方法。)将第二个解决方案称为 better one 是完全取决于每个人的个人喜好。 【参考方案1】:

我想说你必须在这里考虑 3 件主要的事情(它们并不完全相同):

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

在您的特定情况下,这取决于您的 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。不要忘记将此方法的结果与 One File 方法进行比较,因为 One File 方法可能仍然更有效。

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 docs):

.extract(['jquery'])

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

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

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

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


所有页面特定文件

如果您的所有页面特定文件都很大,我只会走这条路在不同的文件之间共享。

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

webpack.mix.js

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

你会:

资源/资产/js/index/index.js

require('../app.js')

//rest of file

webpack.mix.js

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

尽管如此,我永远不会直接采用这种方法,而且在极少数情况下它会是最有效的。


总结

我总是会采用 One File 方法,然后再考虑进行优化(除非在开发过程中确实有问题),因为过早的优化会导致代码异味和更难的可维护性。

这对你来说可能也是一篇好文章https://medium.com/@asyncmax/the-right-way-to-bundle-your-assets-for-faster-sites-over-http-2-437c37efe3ff

【讨论】:

一个js文件会不会导致问题,因为js需要按顺序加载? @FabricioG 我从来没有遇到过问题。

以上是关于使用 Laravel Mix 合并多个文件的主要内容,如果未能解决你的问题,请参考以下文章

Laravel MIX,如何在多个文件中使用单个函数

Laravel 5.4 Webpack Mix - 合并SCSS和CSS

如何混合多个入口点并同时观看 laravel mix

如何在 Laravel 7 中使用 Webpack.mix.js 使用多个 js?

关于Laravel中使用Laravel-mix打包资源文件的一个坑

Laravel 5 - 文件上传