Laravel Mix: What is the benefit of extracting vendors? - laravel

My minified bundle size is 246kb. I am seeing if I can getting smaller and I read that extracting vue and jquery using mix.extract(['vue', 'jquery']); can help do this. I added this to webpack.mix.js` and now it created 2 files rather than 1. It made: 1) app.js which is 161kb and 2) vendor.js which is 180kb. What is the benefit of this if both need to be included in the page anyways?

This is mainly abut caching unchanged files. For example: while you developing app you are changing the files, adding your own code to your project and then recompile them all together. But vendors are the core libraries which you are never edit their code again. So there is no need to compile them again and download all source code in app.js file. Thus when you extract vendors which they are unchanged files then your cached content size will increase and it also decrease download time of your application because of less changed files must be downloaded again.

It helps you to optimize the file size of the files that client needed to download. Thus speed up the page loading speed even you have updated your site.
Check the documentation.
One potential downside to bundling all application-specific JavaScript with your vendor libraries is that it makes long-term caching more difficult. For example, a single update to your application code will force the browser to re-download all of your vendor libraries even if they haven't changed.

Related

Web Application Speed Performance

I'm using React and bundle with Webpack to create my web application.
My simple question is:
My bundling file is only about ~4.5mb, but my overall repo is ~20mb because of pictures and other assets. My question is does the performance(first opening up pages) of application only affected by my bundle size? or the whole repo?
And Also, what's considered an TOO large of repo or bundling? for average enterprise production application?
What your production app will probably use is what you generate inside the build directory. Sometimes this is only a bundle.js file (the images and styles will be inside), other times you can split the bundle.js file's images and styles in different files, so you would have to include that. It all depends on your setup.
4.5mb is not too much, although it will depend on your server performance too. It is completely normal if it contains all the dependencies. If you need to load some pages faster than the rest, you can split the bundle in multiple files so some parts of your app will not require all the bundle files. This is called code-splitting. You read more about it here.
Normally you will want some simple landing pages to load faster, and it would depend if your website is the mainly used by mobile phones (worse network connections) or laptops (normally using Wifi).

WebPack: Change in module numbers do not change chunkhash

I am using webpack to bundle my files into two file: app.js and lib.js and I create and append unique chunkhash for each of my files that get download by browser. Both these files are built together in the same build output. It would look like this:
lib.747c2ee515b25d871bd0.js
app.e6a0b36a5bb2bff41393.js
I have following caching set on these files:
Cache-Control:private, max-age=31536000
This means that these files will be cached for an year or when a new file arrives. And this would work independently for each file.
Since our application is closer to release, there more changes in app than in lib.
Problem: The problem I am facing is that in a new build, contents of the lib are not changed but module ids are changed. This is causing module ids to change but chunkhash doesn't change; causing downloading of app but not lib resulting into broken app. On Ctrl+F5 everything starts working again as expected.
Questions: Isn't the changed module ids considered as part of chunkash? How do I fix this problem? Is it possible to add auto-increment explicit version number to file names through WebPack?
Any help will be much appreciated.
If you're using webpack-md5-hash plugin to change the webpack chunkhash then you might be hitting this issue.
Also these two articles might help Predictable long term caching and Long term caching of static assets with webpack.
The way I solved this is by adding one more number (which is Date.now()) into my file names as below.
filename: `[name].${Date.now().valueOf()}.[chunkhash].js`
This works pretty reliably for foreseeable time. This is with an understanding that the value returned by Date.now().valueOf() is the number of millisecond since midnight January 1, 1970 UTC. Besides, all I want to achieve here is the value be automatically generated and different from previous one.
The only drawback I see with this method is that: With each release, this forces all the bundles to be refreshed. However, this is not a so much of a concern considering very low frequency of production rollouts we will have after first 2 releases.

How to install node modules but commit only relevant styles

So, I am setting up a new site and my project's folder structure looks like this now.
foo.com/
index.php
assets/
css/
img/
js/
vendor/
I have added vendor/ for js/css libraries that I must install to keep them separate, since I want anyone who installs my project to install those in vendor from package.json - most libraries contain too many files 99% which I don't want to push to production.
Now once the project is finished, I would like to push the code to production with only the necessary js/css files.
This is where the problem comes. For example, if I install bulma css using:
yarn add bulma --modules-folder ./assets/vendor
It will dump all bulma-related files which are almost 70 into /vendor/bulma/ but I will only be needing one or two css files afterwards, since I will compiles the sass file to css as:
sass vendors/bulmna/style.scss assets/css/style.css
So my questions is: I am assuming this is how every developer does it and there are no documentations I can find that suggest how to do it. Is it safe to ignore the /vendor directory? What if I install vue, font-awesome, bootstrap .. how can I only fetch the files I need but not everything in /vendors folder?
Your question is actually quite broad - however, I'll try to list as much as possible.
Lets say you're building a project from scratch and needed to include vuejs, jquery, fontawesome but only need to include a couple of files.
The issue you're hitting here is module dependency with respect to npm modules. (and there are many different tools that you can use to manage versions on your library dependencies as well as ensuring they are included into your project, i.e. package managers).
Ok - now from here, you may say to yourself
but I only need say, one icon from fontawesome in your final build (dist) and I don't want to commit all my modules into source control
Again, this is where you omit node_modules and other dependent libraries from source control (i.e. include node_modules your .gitignore)
To reiterate
You can install the required library,
add node_modules to .gitignore ,
bundle those libraries into a vendor single file to be consumed by your users (can be via browserify/webpack/rollup/gulp/grunt/yarn etc).
generate bundle within npm script
Now you may ask further -
Why would I use any of those tools? - they're distracting me from simply copy/pasting vendor libaries into my source control.
Build tools were created to
streamline the developer pipeline so that you DONT have to copy/paste vendor libaries into a vendor folder.
ensures that all files are bundled to the client automatically
allows you to keep track/restrict library version updates/ when required via package.json
allows you to add other build steps (such as minification, md5hash versioning, compression, code splitting, asset management to name a few).
Now lets break down the original question here:
How to ensure other developers get everything they need when cloning the repository
how do I ensure I can provide only the necessary files to the end user (if I only use specific parts of vendor libaries?)
1. How to ensure developers get what they need
Again, to reiterate above, adding devDependancies and .gitignoring allows you to only add the necessary files to your project.
2. How can I ensure clients get what they need without bloating request files?
This is where build tools such as webpack, browserify, gulp, grunt, rollup, attempt to achieve. This is because with some libraries that exceed in file size of 200kb minified, you may need to separate these files into different client requests (and as such, not demand the user to request one large file, which was symtomatic of browserify projects).
The second technique you will need to be aware of, is with specific libraries, you can use import mdn link where you can require one function/class from a dependant library (which further reduces file size).
Another technique is using less import statements (which can extract less functions/styles similar to above, but this isn't currently supported in SCSS). for SCSS, you're basically left with copy/pasting the necessary styles into your base scss and that'll save you space as well.
EDIT
How to create a bundle from npm install libaries
From the comments you've mentioned above (about not wanting to include a tool into your workflow, there's no point outlining any one particular strategy - you can find answers/tutorials online about how to setup gulp/browserify/webpack for your particular needs).
However, As you are currently using yarn - I'll go into details about that.
Firstly, yarn is a package manager (like npm). All it does with the --modules-folder is install the package into the specified folder, that's all. So we don't really care about that (since it's doing the same thing as npm). (i.e. your vendor folder is the same as node_modules in many respects).
We could use
webpack
gulp
grunt
rollup
browserify
brunch
(All build tools that essentially allow you to bundle all those packages into a single entry point to be packaged to the client).
I won't go into how, because that is a process you can find online, and from the above comments, I can tell you don't particularly care either.
What you are looking for is a zero-config javascript build tool. (Extremely out of the scope of your original question, and i'll only answer that in a separate Q&A).
I'd try Googling on "tree shaking CSS" to see if that gives you something.
Maybe something like: https://github.com/jacobp100/es-css-modules
Rollup plugin may be useful. It works for js, with postcss, the link says it works with css also.
https://code.lengstorf.com/learn-rollup-css
Have a look at Pancake. It has been built specifically for the purpose of moving only those files out of the node_modules folder that you need. I wrote an article about it here: https://medium.com/dailyjs/npm-and-the-front-end-950c79fc22ce
(probably not an answer but a good tip)
PS: I am the author of both, the article and the tool so with clear bias :)

Editing less files in Joomla

I'm beginner in Joomla So please any one help me. I'm editing on less files in both locations (media/guild/less/ and templates//less/) but changes are not reflected in front-end. Why has not reflected changes in the front-end.
It seems that your less files are not compiled to css, so no changes appear. Less can be compiled in the browser using Javascript, or via the commandline. I my opinion, there are only very few cases, in which it makes sense to compile in the browser.
To compile those files from the commandline you can have a look here
If you are new to Less/npm and all other needed stuff, you should have a look at the official docs.
As #philipp points out, Less files need to be compiled before they can be used.
Templates that use Less handle this in different ways. For example, Less files might be recompiled and saved each time you save the template settings. Deleting the Joomla cache and refreshing the front-end of the website might also trigger a recompile of the Less files.
For simple and future proof changes, it is often easier to override the CSS via a custom CSS file compared to editing the Less files directly.

Building fine-uploader without the UI

Fine uploader is 400kb of javascript code and 140kb minified. Since I am not using the UI and only using the API, I would like to build the library without the integrated interface (and hopefully get a smaller lib consequently). Is this possible?
Could not find this in the downloads section.
I've also setup the build environment and built the package myself, but all the files in the _dist dir seem to be bundled with the UI.
Fine Uploader is only 40 kB gzipped, which is compression that pretty much every web server already utilizes. The build is not currently setup to create a bundle without the UI. If you'd like to create such a build, the modules.js file will need to be modified. One place to start would be with a copy of the fuTraditional module sans the #fuSrcUi module. Then, a corresponding entry would need to be added to the concat.js build file. This doesn't seem worth it to save a few kB in my humble opinion, but it's all very possible.
If you're interested in a much more modular upload library where almost every feature is represented as an optional standalone module, take a look at Modern Uploader, which I am slowly developing as time allows. Feel free to open up issues in the repo if you have any questions regarding the future of that product.

Resources