How to include external libraries via CDN asynchronously in Webpack - javascript

Prior to posting this question, I consulted the following threads on this topic:
How to include external CDN link into webpack project
Webpack and external libraries
how to use webpack to load CDN or external vendor javascript lib in js file, not in html file
How to include jQuery CDN in Webpack?
Webpack externals documentation
Based on all the above, it appears that in order to load a third-party library via a CDN, the standard method would be to use webpack externals, which produces the following script tag in the index.html file (per Webpack docs).
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous">
</script>
While this solution works if you have one or two libraries, how are you supposed to load 10 libraries (for arguments sake) via CDNs asynchronously (to maximise pageload performance) using externals in Webpack?
My current solution to this problem is to manually include the following script tags in my index.html file with relevant "async" and "defer" tags; however, I need to update the index.html file in my dist folder every time I include a new library, which leads me to believe I'm doing this completely wrong. Below is what my index.html file currently looks like, which is also replicated in the dist folder.
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<link rel="stylesheet" href="https://afeld.github.io/emoji-css/emoji.css">
</head>
<body>
<div id="app"></div>
</body>
<script src="https://cdn.jsdelivr.net/npm/moment#2.20.1/moment.min.js" async defer></script>
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.4/lodash.min.js" async defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/4.0.0/math.min.js" async defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js" async defer></script>
<script src="https://widget.cloudinary.com/global/all.js" async defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js" async defer></script>
<script src="/dist/build.js" async defer></script>
</html>
While I'm sure there's a "hack-ey" way of achieving my goal (which I'm open to seeing), my question is whether I can accomplish the above through an officially supported method (like through externals). If not, how does most of the web development world use libraries given that CDNs are known to almost always improve pageload performance?
EDIT: For some context, I'm using Webpack because I'm using vue-loader to build my VueJS SPA (as a learning project).
EDIT 2: This question was asked using incorrect assumptions about Webpack and how web development works. The conclusion is that you shouldn't be using CDNs as liberally as I have if you're using Webpack. Refer to the comment section for clarification.

Related

React public folder scripts

Calling on the react experts haha.
I am trying to import/include some external javascript files into my React project, these js files cannot be changed or edit as per instructions from my company, as this is a base for many application that uses them.
For reasons i wont be putting the real filenames and folders.
There is a folder in my public folder called "testModules", so path is public/testModules/
all the files / 3 files that i need to include is in there.
What i have tried so far.
In my index.html file at the bottom i have tried the following
<script type="text/JavaScript" src="%PUBLIC_URL%/testModules/test1.js"></script>
<script type="text/JavaScript" src="%PUBLIC_URL%/testModules/test2.js"></script>
<script type="text/JavaScript" src="%PUBLIC_URL%/testModules/test3.js"></script>
and
<script type="text/JavaScript" src="./testModules/test1.js"></script>
<script type="text/JavaScript" src="./testModules/test2.js"></script>
<script type="text/JavaScript" src="./testModules/test3.js"></script>
and
<script type="application/javascript" src="./testModules/test1.js"></script>
<script type="application/javascript" src="./testModules/test2.js"></script>
<script type="application/javascript" src="./testModules/test3.js"></script>
and
Then i have also tried using the ScriptTag plugin "react-script-tag"
with the same examples as above, but instead of %PUBLIC_URL% i used process.env.PUBLIC_URL
When i try any of the above it works on my local development env. For example running npm run start and opening on localhost
But as soon as i move to application to a live server i get the following err
Refused to execute script from 'https://test.com/testModules/test.js'
because its MIME type ('text/html') is not executable, and strict MIME
type checking is enabled.
For all the files i added.
Now i open up my dev console and i can see the scripts are appended/included in the body at the bottom.
What is going on and how can i fix it.
Thanks You
If you wouldn't like to make any improvements to your deployment architecture, then you should pretty much talk to "your backend devs" so that they configure the web server so that this particular route would emit a different MIME type while serving this particular static file.
Alternatively, if possible, you could use Webpack to statically link the third-party code base to your React project so that they are distributed together. This way, if you use any implementation of Javascript modules, you will eliminate this crutch of your library being visible at the scope of the HTML host and this might bring improvement to your codebase.

Adding script in Laravel

I am fairly new to Laravel but I'm getting to grips with it.
At the moment there a partial blade that just includes scripts from the public assets folder, like below.
<script src="{{asset('js/jquery-3.2.1.min.js')}}"></script>
<script src="{{asset('js/bootstrap.js')}}"></script>
<script src="{{asset('js/bootstrap.js')}}"></script>
<script src="{{asset('assets/library/slick/slick.js')}}"></script>
<script src="{{asset('assets/library/slick/slick-init.js')}}"></script>
<script src="{{asset('assets/library/tinymce/jquery.tinymce.min.js')}}"></script>
<script src="{{asset('assets/library/tinymce/tinymce.min.js')}}"></script>
<script src="{{asset('assets/library/tinymce/tinymce-settings.js')}}"></script>
<script src="{{asset('js/isotope-docs.min.js')}}"></script> <!-- JQuery and Bootstrap JS -->
<script src="{{asset('js/app.js')}}"></script>
<script src="{{asset('js/grid.js')}}"></script>
<script src="{{asset('vendor/laravel-filemanager/js/lfm.js')}}"></script>
<script src="{{asset('vendor/laravel-filemanager/js/lfm.js')}}"></script>
I feel like this is a bit messy and far from optimal.
I did some poking around in resources/assets/js and saw that by default Laravel uses bootstrap.js and then grabs this in app.js. Also the items in bootstrap.js seem to be grabbed directly from the node_modules folder.
Is it better practice to instead include all the JavaScript libraries in bootstrap.js?
If so, could I install all these libraries via NPM and somehow include them in the bootstrap.js file? At least the ones that are available via npm.
Then in my footer I could just include app.js instead of my individual scripts.
You can use Laravel mix to concatenate, minify/uglify your JS, style assets.
Laravel mix documentation

Converting an IIFE to module.exports (and use Webpack)

I want to start using Webpack.
Currently, in one project I have the next lines:
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.js"></script>
<script defer src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script defer src="/js/doubletaptogo.js"></script>
<script defer src="/js/init.js"></script>
I guess the following:
I should not download modernizr neither jquery because both are downloaded from their respective CDNs.
DoubleTapToGo is also a library and it is a minified local file. It is expressed via an immediately invoked function expression. So I should convert it into a module using module.exports, but I don't know how to do that and if I really should:
init.js should require DoubleTapToGo as a module, to produce just one file and finally have 2 libraries and 1 local JS file.
Please correct me.
Thank you in advance.
doubletaptogo.js has the following content:
;(function($,window,document,undefined){$.fn.doubleTapToGo=function(params){if(!('ontouchstart'in window)&&!navigator.msMaxTouchPoints&&!navigator.userAgent.toLowerCase().match(/windows phone os 7/i))return false;this.each(function(){var curItem=false;$(this).on('click',function(e){var item=$(this);if(item[0]!=curItem[0]){e.preventDefault();curItem=item;}});$(document).on('click touchstart MSPointerDown',function(e){var resetItem=true,parents=$(e.target).parents();for(var i=0;i<parents.length;i++)if(parents[i]==curItem[0])resetItem=false;if(resetItem)curItem=false;});});return this;};})(jQuery,window,document);

How to work with src file and keep the directory clean (from compiled files)?

The reason to have src and dist folders is pretty clear: we change source code commit it to repository and use compiled dist files for production.
But what could you recommend for development? We still want to keep src clean from compiled file and make it very fast to review the changes.
Before we just transpiled SAAS into CSS and put it into source and keep JS files as they are(without compiling in one file or coping them to dist). And now we decided to rethink the concept.
we are doing web development, but I think question is more broad.
If I well understood, you are looking for a development architecture/workflow to directly serve you sources to the browser (and use DevTools edition features btw). In fact, there are 2 things to do to achieve this.
1) For compiled/transpiled languages (SAAS, LESS, TypeScript, ...) and unsupported languages (ES6, ES7), you will need to compile/transpile them on the client side. Tools like LESS.js, typescript.js, BabelJS are great to do that. I don't know any SAAS compiler implementation in Javascript.
2) Then, you need 2 different html indexes. For example index.hml for production and dev.html for development.
index.html with bundled (dist) files:
<!DOCTYPE html>
<html>
<head>
<title>App Title</title>
<link rel="stylesheet" type="text/css" href="dist/app.bundle.css">
<script type="text/javascript" src="dist/app.bundle.js"></script>
</head>
<body>
...
</body>
</html>
dev.html with all sources (src) files:
<!DOCTYPE html>
<html>
<head>
<title>App Title (Dev)</title>
<link rel="stylesheet/less" type="text/css" href="src/file1.less" />
<script type="text/javascript" src="src/file1.js"></script>
<script type="text/javascript" src="src/file2.js"></script>
<script type="text/javascript" src="src/file3.js"></script>
<script type="text/javascript" src="lib/less.js"></script>
</head>
<body>
...
</body>
</html>
This way, developers access the web app using, let's say http://localhost/dev.html and can enjoy all the goodness to have sources right in the browser. Without taking care of the compilation.
To apply such an architecture you may need to adapt client and/or server code and also build tools to work in both mode (prod and dev).
Hope I helped.

How can you specify which requirejs modules should load in a html file

I can't find an answer to this anywhere. Does this need to be done or does the optimiser do this somehow?
If a minified requirejs file became very large would it be suitable to break my_main.js down and possibly use my_main1 and my_main2?
<script type="text/javascript" data-main="my_main.js" src="scripts/require.js"></script>
You specify which modules you want via your "require" and "define" calls...
Your index.html will have a tag such as:
<script type="text/javascript" data-main="my_main.js" src="scripts/require.js"></script>
Inside "my_main.js" you'd do something like:
require(["module1", "module2"], function(module1, module2) {
});
which would load in module1 and module2.
When you decide to optimise your code, the optimiser will look through all the modules you load and all their dependencies and put them in a single minified file. You'll only need to load that minified file in your index.html in an optimized build.

Categories