23

I am currently in the process of diving into Laravel Mix and so far, whilst I fully understand what Laravel Mix is and how it works, I am trying to understand a little more about the common practices and 'How-Tos'...

For instance, consider this file structure:

/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)

Now, ideally, I would like the following combined and minified in the following way:

/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)

As far as I understand, the way to achieve this is something like the following:

// 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();

My Question

Quite simply, I would like to know if the above is the correct method for doing what I am trying to do? Are there better ways, or more common ways of achieving this?

If the above structure is wrong and there are other ways my files should be combined then please share your knowledge. However, unless there is a very good reason, I would like to avoid the following:

  • Serving two separate files for each page i.e. app.min.js and index.min.js. This requires two lookups per page, ideally it should be as few as possible
  • Serving the same file to ALL pages on my site. Serving code to a page that is not going to use it is a waste of resource, regardless of caching...

One Idea...

I noticed a line of code in one of the JS files; require('./bootstrap');. Call me old fashioned but I have never seen this in JavaScript (I assume it is from node.js). That said, obviously it is just loading the bootstrap.js file as a dependency into the specific file. So, with this in mind, would the following solution be better:

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

If this is a better solution then how do I include files using SASS as well? Are there ways the above can be improved at all?

4

1 回答 1

33

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

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

在您的特定情况下,这将取决于您的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.

解决这个问题的一种方法是使用供应商提取Laravel Mix docs):

.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();

你将会拥有:

资源/资产/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

于 2017-07-16T10:08:06.607 回答