├── .gitignore ├── lazy-loading-dynamic-import ├── src │ ├── views │ │ ├── about.mjs │ │ ├── help.mjs │ │ ├── home.mjs │ │ └── contact.mjs │ ├── index.js │ ├── routerConfig.mjs │ └── router.mjs ├── readme.md ├── package.json └── index.html ├── .github ├── workflows │ └── set-default-labels.yml └── labels.json ├── README.md ├── CODE_OF_CONDUCT.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .DS_Store 3 | build 4 | dist 5 | node_modules 6 | .cache -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/src/views/about.mjs: -------------------------------------------------------------------------------- 1 | export default ` 2 |

About

3 | `; -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/src/views/help.mjs: -------------------------------------------------------------------------------- 1 | export default ` 2 |

Help

3 | `; -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/src/views/home.mjs: -------------------------------------------------------------------------------- 1 | export default ` 2 |

Home

3 | `; -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/src/views/contact.mjs: -------------------------------------------------------------------------------- 1 | export default ` 2 |

Contact

3 | `; -------------------------------------------------------------------------------- /.github/workflows/set-default-labels.yml: -------------------------------------------------------------------------------- 1 | name: set-default-labels 2 | on: [workflow_dispatch] 3 | 4 | jobs: 5 | set-default-labels: 6 | uses: mdn/workflows/.github/workflows/set-default-labels.yml@main 7 | with: 8 | target-repo: "mdn/perf-examples" 9 | should-delete-labels: true 10 | -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/readme.md: -------------------------------------------------------------------------------- 1 | # Lazy Loading - Dynamic Import 2 | 3 | This demo includes a simple router implementation that lazy loads the different views as they are accessed. 4 | 5 | ## To run the demo 6 | 7 | Get the demo 8 | 9 | ``` 10 | git clone https://github.com/garyvh2/perf-examples.git 11 | cd Lazy Loading - Dynamic Import 12 | ``` 13 | 14 | Run the demo 15 | 16 | ``` 17 | npm install 18 | npm start 19 | ``` 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Performance examples 2 | 3 | > [!NOTE] 4 | > This repository is archived as of December 2023. 5 | > Many thanks to everyone who contributed! 🎉 6 | > 7 | > For MDN documentation about performance, see https://developer.mozilla.org/en-US/docs/web/Performance. 8 | 9 | ## Demos included 10 | 11 | - [Lazy Loading Demo](https://garyvh2.github.io/perf-examples/lazy-loading-dynamic-import/) from [Lazy-loading JavaScript with import()]() 12 | -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import { Router } from './router.mjs'; 3 | 4 | /** Elements */ 5 | const routerOutlet = document.getElementById('outlet'); 6 | 7 | /** Router */ 8 | import('./routerConfig.mjs').then(({ 9 | routerConfig 10 | }) => { 11 | const routerInstance = new Router(routerConfig, routerOutlet); 12 | routerInstance.renderPage(location.pathname || '/perf-examples/lazy-loading-dynamic-import/'); 13 | }); -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/src/routerConfig.mjs: -------------------------------------------------------------------------------- 1 | export const routerConfig = { 2 | '/': () => import('./views/home.mjs'), 3 | '/perf-examples/lazy-loading-dynamic-import/': () => import('./views/home.mjs'), 4 | '/perf-examples/lazy-loading-dynamic-import/help': () => import('./views/help.mjs'), 5 | '/perf-examples/lazy-loading-dynamic-import/about': () => import('./views/about.mjs'), 6 | '/perf-examples/lazy-loading-dynamic-import/contact': () => import('./views/contact.mjs') 7 | } -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lazy-loading-dynamic-import", 3 | "version": "1.0.0", 4 | "description": "Lazy Loading example with dynamic import", 5 | "main": "index.html", 6 | "scripts": { 7 | "start": "parcel index.html --open", 8 | "build": "parcel build index.html" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/mdn/perf-examples.git" 13 | }, 14 | "author": "garyvh2", 15 | "license": "CC0-1.0", 16 | "bugs": { 17 | "url": "https://github.com/mdn/perf-examples/issues" 18 | }, 19 | "homepage": "https://github.com/mdn/perf-examples#readme", 20 | "dependencies": { 21 | "parcel": "^1.12.3" 22 | } 23 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Participation Guidelines 2 | 3 | This repository is governed by Mozilla's code of conduct and etiquette guidelines. 4 | For more details, please read the 5 | [Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). 6 | 7 | ## How to Report 8 | For more information on how to report violations of the Community Participation Guidelines, please read our [How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/) page. 9 | 10 | 16 | -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Lazy Loading - Dynamic Import 9 | 10 | 11 | 12 | 13 | Home 14 | About 15 | Help 16 | Contact 17 | 18 |
19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /lazy-loading-dynamic-import/src/router.mjs: -------------------------------------------------------------------------------- 1 | export class Router { 2 | constructor(config, outlet) { 3 | /** Store Properties locally */ 4 | this.config = config; 5 | this.outlet = outlet; 6 | 7 | /** Add Listener to links */ 8 | document.addEventListener('click', (event) => this.linkListener(event), true); 9 | window.addEventListener('popstate', (event) => this.popstateListener(event), true); 10 | } 11 | 12 | /** 13 | * Listener for window popstate events 14 | * @param event popstate event 15 | */ 16 | popstateListener(event) { 17 | if (this.config[location.pathname]) { 18 | this.renderPage(location.pathname); 19 | } 20 | } 21 | 22 | /** 23 | * Listener for anchor elements click 24 | * @param event 25 | */ 26 | linkListener(event) { 27 | /** If the element clicked is an anchor */ 28 | if (event.target instanceof HTMLAnchorElement) { 29 | const { 30 | pathname 31 | } = event.target; 32 | /** If the path of the link is in the configuration */ 33 | if (this.config[pathname]) { 34 | event.preventDefault(); 35 | this.renderPage(pathname); 36 | } 37 | } 38 | } 39 | 40 | /** 41 | * Fetches and renders a view based on the url 42 | * The router takes the configuration with the format 43 | * 44 | * { 45 | * '/pathname': () => import('./view/filename') 46 | * } 47 | * 48 | * So whenever a route event is triggered, the location is pushed into the history 49 | * and the dynamic import of the view is executed 50 | * 51 | * Then the outlet innerHTML is set to the view content 52 | * 53 | * @param href url 54 | */ 55 | renderPage(href) { 56 | /** Fetch and render, dynamically */ 57 | this.config[href]().then((view) => { 58 | this.setOutletContent(view.default); 59 | /** Push new state */ 60 | history.pushState(null, null, href); 61 | }); 62 | } 63 | 64 | /** 65 | * sets the HTML content 66 | * @param content html content 67 | */ 68 | setOutletContent(content) { 69 | this.outlet.innerHTML = content; 70 | } 71 | } -------------------------------------------------------------------------------- /.github/labels.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "good first issue", 4 | "color": "028c46", 5 | "description": "A good issue for newcomers to get started with." 6 | }, 7 | { 8 | "name": "help wanted", 9 | "color": "028c46", 10 | "description": "If you know something about this, we would love your help!" 11 | }, 12 | { 13 | "name": "needs info", 14 | "color": "028c46", 15 | "description": "This needs more information to review or act on." 16 | }, 17 | { 18 | "name": "needs triage", 19 | "color": "028c46", 20 | "description": "Triage needed by staff and/or partners. Automatically applied when an issue is opened." 21 | }, 22 | { 23 | "name": "expert help needed", 24 | "color": "028c46", 25 | "description": "This needs more information from a subject matter expert (SME)." 26 | }, 27 | { 28 | "name": "idle", 29 | "color": "028c46", 30 | "description": "Issues and pull requests with no activity for three months." 31 | }, 32 | { 33 | "name": "on hold", 34 | "color": "028c46", 35 | "description": "Waiting on something else before this can be moved forward." 36 | }, 37 | { 38 | "name": "for later", 39 | "color": "028c46", 40 | "description": "Not planned at this time." 41 | }, 42 | { 43 | "name": "needs content update", 44 | "color": "028c46", 45 | "description": "Needs update to the content to support this change." 46 | }, 47 | { 48 | "name": "chore", 49 | "color": "028c46", 50 | "description": "A routine task." 51 | }, 52 | { 53 | "name": "enhancement", 54 | "color": "028c46", 55 | "description": "Improves an existing feature." 56 | }, 57 | { 58 | "name": "bug", 59 | "color": "c05964", 60 | "description": "Indicates an unexpected problem or unintended behavior." 61 | }, 62 | { 63 | "name": "wontfix", 64 | "color": "c05964", 65 | "description": "Deemed to be outside the scope of the project or would require significant time and resources to fix." 66 | }, 67 | { 68 | "name": "effort: small", 69 | "color": "866dc1", 70 | "description": "Task is a small effort." 71 | }, 72 | { 73 | "name": "effort: medium", 74 | "color": "866dc1", 75 | "description": "Task is a medium effort." 76 | }, 77 | { 78 | "name": "effort: large", 79 | "color": "866dc1", 80 | "description": "Task is large effort." 81 | }, 82 | { 83 | "name": "p0", 84 | "color": "6e8bc1", 85 | "description": "Urgent. We will address this as soon as possible." 86 | }, 87 | { 88 | "name": "p1", 89 | "color": "6e8bc1", 90 | "description": "We will address this soon and will provide capacity from our team for it in the next few releases." 91 | }, 92 | { 93 | "name": "p2", 94 | "color": "6e8bc1", 95 | "description": "We want to address this but may have other higher priority items." 96 | }, 97 | { 98 | "name": "p3", 99 | "color": "6e8bc1", 100 | "description": "We don't have visibility when this will be addressed." 101 | } 102 | ] 103 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | --------------------------------------------------------------------------------