Javascript Modify the Script and Execute Again
The author selected Artistic Eatables to receive a donation as part of the Write for DOnations program.
Introduction
External libraries can add complexity to a new JavaScript project. To exist able to install and use external lawmaking libraries, yous'll need a build tool that tin can parse the code and package the libraries that you lot import into a last format. After the build is set up, you can add and integrate new lawmaking with ease, but there are even so some problems.
For case, you lot may demand a library in simply one office of your application, a function of the application most users may never need, like an admin folio. Just by default most build systems volition bundle all the code into one large file. The user will load the lawmaking regardless of whether they e'er demand to execute it. The build systems are flexible plenty that they can be configured to load code as needed, but the process takes some work.
Build tools are an of import office of the development experience, but a spec chosen import maps will allow yous to both import external lawmaking into your project without a build tool and information technology will but load the code when it is needed at runtime. Import maps won't completely replace build tools that perform many other valuable actions like building style sheets and treatment images, merely they volition let you lot to bootstrap new JavaScript applications quickly and easily using but the native browser functionality.
In this tutorial, yous'll apply import maps and JavaScript modules to import code without build tools. Yous'll create a basic application that will display a message and you'll create an import map that will tell your browser where to locate external code. Next, you'll integrate the imported code into your JavaScript and volition utilise the third-party code without any demand to download the lawmaking locally or run information technology through a build step. Finally, yous'll learn about current tools that implement many aspects of import maps and work on all modern browsers.
Prerequisites
-
Yous will need a evolution environment running Node.js. This tutorial was tested on Node.js version fourteen.17.1 and npm version vi.fourteen.23. To install this on macOS or Ubuntu eighteen.04, follow the steps in How To Install Node.js and Create a Local Development Surround on macOS or the Installing Using a PPA section of How To Install Node.js on Ubuntu 18.04.
-
You will also need a bones knowledge of JavaScript, which y'all tin find in How To Code in JavaScript, along with a basic knowledge of HTML and CSS. A good resources for HTML and CSS is the Mozilla Programmer Network.
Step one — Creating an HTML Page and Inserting JavaScript
In this step, you volition create an HTML page, use JavaScript for dynamic activity, and start a local development server to track your changes.
To starting time, in a new directory, create a blank HTML certificate.
Open a file chosen index.html
in a text editor:
- nano index.html
Within of the file, add a brusk, bare HTML page:
index.html
<! DOCTYPE html > <html lang = "en-US" > <caput > <meta charset = "utf-8" > <meta http-equiv = "X-UA-Compatible" content = "IE=edge" > <championship > Hello World </title > <meta proper name = "viewport" content = "width=device-width, initial-calibration=1" > </head > <body > </body > </html >
This document has a few standard <meta>
tags and an empty <torso>
element.
Side by side add a <script>
tag. The src
aspect for the script tag will be a new JavaScript file y'all are nigh to create called how-do-you-do.js
:
alphabetize.html
<! DOCTYPE html > <html lang = "en-United states" > <head > <meta charset = "utf-8" > <meta http-equiv = "X-UA-Uniform" content = "IE=border" > <championship > Howdy World </title > <meta name = "viewport" content = "width=device-width, initial-scale=1" > <script defer src = "./hello.js" > </script > </head > <body > </body >
Find that yous are adding a defer
attribute to the <script>
tag. This will filibuster execution of the script tag until after the document is parsed. If you don't defer, you may receive an error that says body
is not establish when you try to add to the chemical element.
Side by side, create a JavaScript file named hello.js
in the same directory asindex.html
:
- nano hello.js
Within of the file, write some JavaScript to create a new text element with the text "Hello, World"
:
hello.js
const el = document. createElement ( 'h1' ) ; const words = "Howdy, World!" const text = certificate. createTextNode (words) ; el. appendChild (text) ; certificate.body. appendChild (el) ;
At present that y'all have your script, you tin can open up the index.html
file in a browser. In the same directory every bit your index.html
file, run npx serve
. This will run the serve
package locally without downloading into your node_modules
. The serve
parcel runs a uncomplicated webserver that will serve your code locally.
npx serve
The command will ask yous if yous want to install a package. Type y
to agree:
Need to install the following packages: serve Ok to proceed? (y) y
When you run the command you will run into some output like this:
npx: installed 88 in fifteen.187s ┌────────────────────────────────────────┐ │ │ │ Serving! │ │ │ │ Local: http://localhost:5000 │ │ │ │ Copied local address to clipboard! │ │ │ └────────────────────────────────────────┘
When you open your web browser to http://localhost:5000
, you'll meet your code. Yous can either exit the server running in a separate tab or window or shut it with CTRL+C
after previewing your code.
At present you are displaying a basic folio in your browser, simply y'all are not yet able to take advantage of 3rd-political party code and JavaScript packages. In the side by side footstep, you'll dynamically import code and import the functions into your script without a build tool.
Step 2 — Writing a Howdy World Script Using ES6 Modules
In this pace, you lot'll write lawmaking that uses external packages. You lot'll modify your code to import JavaScript lawmaking using ES imports. Finally, you lot'll load the code in your browser using the module
type then the browser will know to dynamically load the lawmaking.
To brainstorm, open up upwardly hello.js
:
- nano howdy.js
You are going to import some code from lodash
to dynamically change your text.
Inside of the file, change the text from Hello World
to all lower case: hello world
. And then at the top of the file, import the startCase
function from lodash
using the standard ES6 import
syntax:
hello.js
import startCase from '@lodash/startCase' ; const el = document. createElement ( 'h1' ) ; const words = "hello, world" ; const text = certificate. createTextNode (words) ; el. appendChild (text) ; document.body. appendChild (el) ;
Finally, telephone call startCase
with the words
variable as an argument within of certificate.createTextNode
:
hello.js
import startCase from '@lodash/startCase' ; const el = document. createElement ( 'h1' ) ; const words = "hello, world" ; const text = certificate. createTextNode ( startCase (words) ) ; el. appendChild (text) ; document.body. appendChild (el) ;
If you closed your webserver, open a new terminal window or tab and run npx serve
to restart the server. Then navigate to http://localhost:5000
in a web browser to view the changes.
When you preview the code in a browser, open the developer console. When yous exercise, you'll run across an error:
Output
Uncaught SyntaxError: Cannot utilize import statement outside a module
Since the code is using import
statements, you'll demand to modify the <script>
tag inside of index.html
to handle JavaScript that is now dissever betwixt multiple files. Ane file is the original code you wrote. The other file is the lawmaking imported from lodash. JavaScript code that imports other code are called modules
.
Shut hullo.js
and open index.html
:
- nano index.html
To run the script as a module, alter the value of the type
attribute on the <script>
tag to module
:
hello.js
<! DOCTYPE html > <html lang = "en-Usa" > <caput > <meta charset = "utf-8" > <meta http-equiv = "X-UA-Compatible" content = "IE=border" > <title > Hi World </championship > <meta name = "viewport" content = "width=device-width, initial-scale=1" > <script type = "module" src = "./hello.js" > </script > </head > <body > </torso > </html >
Notice, you lot likewise removed the defer
aspect. JavaScript modules will not execute until the page is parsed.
Open your browser and you'll all the same see an error`:
Output
Uncaught TypeError: Failed to resolve module specifier "@lodash/startCase". Relative references must start with either "/", "./", or "../"
Now the trouble is not the import
argument. The trouble is the browser doesn't know what the import
statement means. Information technology's expecting to find lawmaking on the webserver, so it looks for a file relative to the electric current file. To solve that trouble, you'll need a new tool called import maps
.
In this step, you learned how to modify your JavaScript code to load external libraries using ES imports. You also modified the HTML script
tag to handle JavaScript modules.
In the next step, you'll tell the browser how to observe code using import maps
.
Footstep three — Loading External Code with Import Maps
In this footstep, you'll larn how to create import maps to tell your browser where to find external code. You'll also acquire how to import module code and come across how code is lazy-loaded in a browser.
An import map
is a JavaScript object where the key is the proper noun of the import (@lodash/startCase
) and the value is the location of the lawmaking.
Inside of index.html
add a new script
tag with a type
of importmap
. Inside of the script
tag, create a JavaScript object with a central of imports
. The value volition be another object:
hullo.js
<! DOCTYPE html > <html lang = "en-United states" > <caput > <meta charset = "utf-8" > <meta http-equiv = "10-UA-Compatible" content = "IE=edge" > <title > Hello World </title > <meta name = "viewport" content = "width=device-width, initial-calibration=1" > <script blazon = "importmap" > { "imports" : { } } </script > <script type = "module" src = "./hello.js" > </script > </caput > <body > </trunk > </html >
Be sure that yous do non add together any trailing commas in the object. The browser will not know how to handle them.
Now that y'all have your bones object, you tin can add the location of your code. The structure of an import map will exist like this:
{ "imports" : { "nameOfImport" : "locationOfCode" , "nameOfSecondImport" : "secondLocation" } }
You already know the name of your import @lodash/startCase
, simply now you demand to find where a location to betoken the import map to.
A great resource is unpkg. Unpkg is a content commitment network (CDN) for any package in npm
. If you tin can npm install
a packet, you should exist able to load it via unpkg. Unpkg also includes a browsing option that can help you lot notice the specific file you lot need.
To find the startCase
lawmaking, open https://unpkg.com/scan/lodash-es@4.17.21/ in a browser. Detect the give-and-take browse
in the URL. This gives you lot a graphical way to look through the directory, simply you should not add the path to your import map since information technology serves up an HTML page and non the raw JavaScript file.
Also, note that you are browsing lodash-es
and non lodash
. This is the lodash
library exported as ES modules, which is what you will need in this case.
Scan the lawmaking and you'll detect there is a file called startCase.js
. This lawmaking imports other functions and uses them to convert the outset alphabetic character of each give-and-take to upper case:
import createCompounder from './_createCompounder.js' ; import upperFirst from './upperFirst.js' ; /** * Converts `string` to * [start instance](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). * * @static * @memberOf _ * @since iii.i.0 * @category String * @param {string} [cord=''] The string to convert. * @returns {string} Returns the kickoff cased cord. * @case * * _.startCase('--foo-bar--'); * // => 'Foo Bar' * * _.startCase('fooBar'); * // => 'Foo Bar' * * _.startCase('__FOO_BAR__'); * // => 'FOO BAR' */ var startCase = createCompounder ( office ( result, word, index ) { return consequence + (index ? ' ' : '' ) + upperFirst (discussion) ; } ) ; export default startCase;
The browser volition follow the import
statements and import every file necessary.
Now that you lot accept a location for your import map, update the file import map with the new URL. Inside of alphabetize.html
, add @lodash/startCase
along with the URL. Once more, be certain to remove browse
:
index.html
<! DOCTYPE html > <html lang = "en-US" > <head > <meta charset = "utf-viii" > <meta http-equiv = "10-UA-Compatible" content = "IE=edge" > <title > Hello World </title > <meta proper name = "viewport" content = "width=device-width, initial-scale=1" > <script type = "importmap" > { "imports" : { "@lodash/startCase" : "https://unpkg.com/lodash-es@4.17.21/startCase.js" } } </script > <script type = "module" src = "./hello.js" > </script > </caput > <body > </torso > </html >
Save the file. Refresh your browser and you volition see Hello World.
NOTE: Import maps are non yet widely supported. Open the lawmaking in the latest version of Edge or Chrome or bank check out the latest supported browsers.
Your browser shows "Hello World", but at present something much more interesting is happening. Open the browser panel in your browser, select Audit Elements, and switch to the Network tab.
After opening the Network tab, refresh the page and you'll meet that the browser is loading the code dynamically. Whenever it finds a new import
statement, information technology imports the relevant code:
More importantly, notice that all of the code is loaded lazily. That means that the browser does not import any code until it is specifically needed. For example, even though startCase
is in the import map and the import map is defined before the script for hello.js
, it is non loaded until afterward hullo.js
loads and imports the code.
If you were to add other entries in your import map, the browser would not load them at all since they are never imported into code. The import map is a map of locations, and doesn't import any code itself.
One major trouble is that import maps are not yet fully supported by all browsers. And fifty-fifty when they are supported, some users may non use a supported browser. Fortunately, in that location are different projects that use the import map syntax while adding total browser support.
In this footstep you created an import map. You likewise learned how to import module code and how the lawmaking will be lazy loaded in the browser. In the adjacent step, y'all'll import lawmaking using SystemJS.
Step iv — Building Cross-Browser Support with SystemJS
In this step, you'll use import maps beyond all browsers using SystemJS. Yous'll export code as a SystemJS build and how to gear up the import map type to use SystemJS format. By the cease of this footstep, y'all'll be able to take advantage of import maps in any browser and volition have a foundation for building more than circuitous applications and microfrontends.
Import maps volition remove many of the complicated build steps from an application, merely they are non yet widely supported. Further, non all libraries are congenital as ES modules so at that place is some limitation to how you lot can use them in your code.
Fortunately, there is a projection chosen SystemJS that can use create import maps for cross-browser support and use a variety of package builds.
The lodash library is convenient because it is compiled in an ES format, but that's not the case for well-nigh libraries. Many libraries are exported in other formats. I of the most common is the Universal Module Definition or UMD. This format works in both browsers and node modules.
A major difference is that dissimilar the ES imports, a UMD build typically combines all of the code into a single file. The file will be a lot larger and you'll end up with more code then yous'll probably execute.
To update your projection to apply SystemJS and a UMD build of lodash, beginning open hi.js
:
- nano hi.js
Alter the import
argument to import the startCase
function direct from lodash
.
hello.js
import { startCase } from 'lodash' ; const el = certificate. createElement ( 'h1' ) ; const words = "hello, earth" ; const text = document. createTextNode ( startCase (words) ) ; el. appendChild (text) ; document.torso. appendChild (el) ;
Relieve and close the file.
Next, to build the file as a SystemJS build, you will need a elementary build step. Yous can use another build tool such as webpack, merely in this instance you'll use rollup
.
First, initialize the project to create a package.json
file. Add the -y
flag to have all of the defaults:
npm init -y
After the command runs y'all'll run into a success output:
{ "name" : "hello", "version" : "i.0.0", "description" : "", "main" : "alphabetize.js", "devDependencies" : { }, "scripts" : { "test" : "echo \"Error: no exam specified\" && leave 1" }, "keywords" : [ ], "author" : "", "license" : "ISC", "homepage" : "" }
Note: Your output may be slightly different depending on the version of npm
you are using.
Next, install rollup
every bit a devDepenceny
:
npm install --save-dev rollup
After a moment, you lot will come across a success message:
+ rollup@2.56.two added 1 package from 1 contributor and audited 2 packages in vi.85s found 0 vulnerabilities
Next, create a unproblematic build configuration. Open up a new file called rollup.config.js
:
- nano rollup.config.js
Then add together a configuration that volition output the code in SystemJS format:
rollup.config.js
consign default { external : [ "lodash" ] , input : [ "how-do-you-do.js" ] , output : [ { dir : "public" , format : "organisation" , sourcemap : true } ] } ;
The external
key tells rollup not to include any of the lodash lawmaking in the final build. SystemJS will load that code dynamically when information technology is imported.
The input
is the location of the root file. The output
tells rollup where to put the terminal lawmaking and the format it should apply which in this case is system
.
Save and shut the file.
At present that you have a build step, you'll demand to add together a task to run information technology. Open package.json
:
- nano parcel.json
In the scripts
object, add a script called build
that will run rollup -c
. Modify the main
key to hello.js
:
package.json
{ "proper noun" : "how-do-you-do" , "version" : "1.0.0" , "description" : "" , "main" : "how-do-you-do.js" , "devDependencies" : { "rollup" : "^two.56.two" } , "scripts" : { "build" : "rollup -c" } , "keywords" : [ ] , "author" : "" , "license" : "ISC" , "homepage" : "" }
Salve and close the file, and run the build
command:
npm run build
The command will run briefly, then you will encounter a success message:
> rollup -c howdy.js → public... created public in 21ms
You lot will also see a new directory called public
that volition contain the built file. If you lot open public/howdy.js
you lot'll see your project compiled in a organization format.
- nano public/hi.js
The file will expect like this. Information technology's similar to hello.js
with a surrounding System.register
method. In addtion, lodash
is in an array. This will tell SystemJS to load the external library during run fourth dimension. Ane of the maintainers created a video that farther explains the module format.
public/hello.js
System. annals ( [ 'lodash' ] , function ( ) { 'use strict' ; var startCase; return { setters : [ function ( module ) { startCase = module.startCase; } ] , execute : function ( ) { const el = certificate. createElement ( 'h1' ) ; const words = "hello, world" ; const text = document. createTextNode ( startCase (words) ) ; el. appendChild (text) ; certificate.torso. appendChild (el) ; } } ; } ) ; //# sourceMappingURL=hello.js.map
Save and close the file.
The concluding step is to update your index.html
to handle the new file:
Open index.html
- nano index.html
First, you'll demand to import the SystemJS code. Use a regular <script>
tag with the src
attribute pointing to a CDN distribution.
Put the <script>
tag right below the import map:
index.html
<! DOCTYPE html > <html lang = "en-US" > <head > <meta charset = "utf-8" > <meta http-equiv = "X-UA-Compatible" content = "IE=edge" > <title > Hello World </title > <meta name = "viewport" content = "width=device-width, initial-calibration=1" > <script type = "importmap" > { "imports" : { "@lodash/startCase" : "https: / /unpkg.com/lodash-es@4.17 .21 /startCase.js } } </script > <script src = "https://cdn.jsdelivr.cyberspace/npm/systemjs/dist/arrangement.js" > </script > <script type = "module" src = "./hello.js" > </script > </head > <trunk > </body > </html >
Next, you'll demand to update your import map. The format is similar to what you completed in Step 3, merely there are three changes:
- Update the import map
blazon
. - Update the reference to
lodash
. - Add a reference to the
hello.js
script.
First, update the type
. Since this is not the native browser version of an import map, but a systemjs
version, change the blazon to systemjs-importmap
:
alphabetize.html
<! DOCTYPE html > <html lang = "en-U.s.a." > <head > <meta charset = "utf-8" > <meta http-equiv = "Ten-UA-Compatible" content = "IE=border" > <title > Hullo World </title > <meta proper name = "viewport" content = "width=device-width, initial-calibration=1" > <script blazon = "systemjs-importmap" > { "imports" : { "@lodash/startCase" : "https: / /unpkg.com/lodash-es@iv.17 .21 /startCase.js } } </script > <script src = "https://cdn.jsdelivr.net/npm/systemjs/dist/system.js" > </script > <script type = "module" src = "./hello.js" > </script > </head > <body > </body > </html >
Side by side, update the references. Alter @lodash/startCase
to lodash
. You'll exist importing the full library. And then alter the location to the UMD build at unpkg.
Then add together a new entry for hello
and indicate that to the compiled version in the public
directory:
alphabetize.html
... <meta name = "viewport" content = "width=device-width, initial-scale=1" > <script type = "systemjs-importmap" > { "imports" : { "hello" : "./public/hello.js" , "lodash" : "https://unpkg.com/lodash@4.17.21/lodash.js" } } </script > ...
Now that you are importing systemJS
and take updated the import maps, all that'south left is to load the module.
Change the blazon
attribute on the script
tag for the module to systemjs-module
. Then alter the src
to import:hello
. This will tell systemjs
to load the how-do-you-do
script and execute:
hello.js
... <script type = "systemjs-importmap" > { "imports" : { "hello" : "./public/hullo.js" , "lodash" : "https://unpkg.com/lodash@4.17.21/lodash.js" } } </script > <script src = "https://cdn.jsdelivr.internet/npm/systemjs/dist/system.js" > </script > <script type = "systemjs-module" src = "import:how-do-you-do" > </script > </caput > ...
Save and close the file.
When you exercise, the browser will refresh and you'll run into How-do-you-do World.
Different native import maps, this will work in whatever browser. Here's the effect in FireFox:
If you wait at the Network tab. You'll see that as with import maps, the code is lazy loaded as needed:
In this step, you lot used import maps across browsers with SystemJS. You lot changed your script to employ the UMD build of lodash, created a rollup build to output the lawmaking in system
format, and changed the import map and module types to work with SystemJS
Conclusion
In this tutorial you used import maps to dynamically load JavaScript code. You rendered an application that dynamically loaded an external library without whatever build step. And then, you lot created a build process to generate your lawmaking in SystemJS format so that you lot can use import maps beyond all browsers.
Import maps give yous opportunities to start breaking large projects into smaller contained pieces called microfrontends. You likewise practise not need to limit yourself to statically defined maps as yous learned in this tutorial; you can too create dynamic import maps that can load from other scripts. You also can employ a single import map for multiple projects by using scopes to ascertain different versions of a dependency for dissimilar scripts that import them.
There are new features in progress and you can follow them on the official spec.
Source: https://www.digitalocean.com/community/tutorials/how-to-dynamically-import-javascript-with-import-maps
0 Response to "Javascript Modify the Script and Execute Again"
Post a Comment