diff --git a/src/manifest.json b/src/manifest.json index 90a0ea033..c9d1135b4 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -3,11 +3,13 @@ "short_name": "Stencil", "start_url": "/", "display": "standalone", - "icons": [{ - "src": "assets/img/icon.png", - "sizes": "512x512", - "type": "image/png" - }], + "icons": [ + { + "src": "assets/img/icon.png", + "sizes": "512x512", + "type": "image/png" + } + ], "background_color": "#16161d", "theme_color": "#16161d" -} \ No newline at end of file +} diff --git a/src/theme/SearchBar/index.tsx b/src/theme/SearchBar/index.tsx index 300c1fac3..c00e9bd0f 100644 --- a/src/theme/SearchBar/index.tsx +++ b/src/theme/SearchBar/index.tsx @@ -1,13 +1,13 @@ import React, { useEffect } from 'react'; -import styles from './index.module.scss' +import styles from './index.module.scss'; type DocSearchProps = { apiKey: string; indexName: string; inputSelector: string; debug: boolean; -} +}; interface CustomWindow extends Window { docsearch: (props: DocSearchProps) => void; @@ -25,7 +25,7 @@ export default function SearchBar() { apiKey: '6399791d239c7e56a6b47685a64f8873', indexName: 'stenciljs', inputSelector: '#algolia-search', - debug: false // Set debug to true if you want to inspect the dropdown + debug: false, // Set debug to true if you want to inspect the dropdown }); }; @@ -42,4 +42,4 @@ export default function SearchBar() { ); -} \ No newline at end of file +} diff --git a/static/blog/how-lazy-loading-works.json b/static/blog/how-lazy-loading-works.json index 852f7c26f..25ae91af1 100644 --- a/static/blog/how-lazy-loading-works.json +++ b/static/blog/how-lazy-loading-works.json @@ -1 +1,243 @@ -{"title":"Stencil Blog - How Lazy-Loading Web Components Work with Stencil","date":"August 15, 2019","url":"/blog/how-lazy-loading-web-components-work","author":"Adam Bradley","twitter":"adamdbradley","description":"When you’re building an app that requires a large library of components in a single file download, you’re often forced to sacrifice performance - and specifically startup time - for the sake of accessing all those components. The two are often mutually exclusive. Choose to easily have all the components available, or choose blazing fast startup, but it’s difficult to get both. At least that’s the experience for many.","img":"/assets/img/blog/posts/stencil-lazy-loading.png","srcPath":"./src/blog/how-lazy-loading-works.md","hypertext":["div",null,["p",null,["img",{"src":"/assets/img/blog/posts/stencil-lazy-loading.png","alt":"Stencil Lazy Loading"}]],"\n",["p",null,"When you’re building an app that requires a large library of components in a single file download, you’re often forced to sacrifice performance - and specifically startup time - for the sake of easily accessing all those components. The two are often mutually exclusive. Choose to have all the components available, or choose blazing fast startup, but it’s difficult to get both. At least that’s the experience for many."],"\n",["p",null,"In fact, downloading and parsing a large set of JavaScript just to show the first page is where many apps struggle, and in many cases “lazy-loading” is a great solution to the problem. Lazy-loading is a term used for loading components only when the end-user requires it, which is a common technique used to speed-up app initialization."],"\n",["p",null,"Stencil, a Web Component compiler used to build custom component libraries and design systems, was originally built for the ",["a",{"href":"https://ionicframework.com/"},"Ionic Framework"],". And Ionic’s challenge has always been to easily distribute a large library of UI components, for both Material Design and iOS, while still staying performant and having a fast startup for Progressive Web Apps. In helping to solve the problem, Ionic moved to using Web Components, which can be distributed and consumed in numerous ways, each with their own pros and cons. But just using Web Components alone does not solve the startup and file size problem."],"\n",["p",null,"We’re often asked “how” Stencil’s lazy loading works, and how one script can serve as a single entry point to a large library. But even further, why has Ionic migrated to this architecture, and how is it able to easily offer a large UI library without file size and startup penalties. In this article I’d like to describe a little further the reasoning behind each decision."],"\n",["p",null,["em",null,"Disclaimer: This is by no means claiming to be the one-true way to lazy load components. In fact there are many ways to lazy-load. This is how Stencil does it, and how Ionic components, developers and users have benefited using Stencil’s technique."]],"\n",["h2",{"id":"script-tags-and-cdns"},"Script Tags and CDNs"],"\n",["p",null,"One of the simplest ways to use a web component is by adding its script tag to the webpage it’ll be used in. When the script loads, it automatically defines the custom element(s), and any custom element already on the page and any created thereafter on the page will get hydrated. Too easy right?"],"\n",["p",null,"For a single component that works great. However, in Ionic’s case, or any large UI library or Design System for that matter, the challenge is that a single script containing every component is often far too large for an acceptable file size or app startup time."],"\n",["p",null,"Even though the first paint may only use a handful of components, by bundling them all into one file the user is penalized by having to download the entire library ",["em",null,"before"]," the user sees the app’s first page. This is thoroughly reviewed in ",["a",{"href":"https://v8.dev/blog/cost-of-javascript-2019"},"The cost of JavaScript in 2019"]," and definitely worth the time to read and digest."],"\n",["p",null,["em",null,"However, do note that Ionic and Stencil components can also be imported into traditional bundlers too. This post is reviewing how lazy-loading works when using the stand-alone script tag way."]],"\n",["h2",{"id":"using-native-browser-features"},"Using Native Browser Features"],"\n",["p",null,"Luckily, browsers already ship with some extremely valuable, and somewhat lesser known, APIs that Ionic (using Stencil) is able to take advantage of. The biggest of those are native ",["a",{"href":"https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/"},"ES Module imports"]," and ",["a",{"href":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports"},"dynamic imports"],"."],"\n",["p",null,"Traditionally within web development, we’ve become accustomed to source code getting transpiled into an unrecognizable ball of JavaScript, requiring the most finely tuned sourcemaps to make sense of it all. The most common of these is transforming the standardized ",["code",null,"import"]," keyword into a deeply nested stack of callbacks in order for JavaScript “modules” to be loaded in an ES5 environment (such as IE11), by often reverting back to the non-standard ",["a",{"href":"https://en.wikipedia.org/wiki/CommonJS"},"CommonJS"]," format."],"\n",["p",null,"With ES Modules now supported natively within browsers, the ",["code",null,"import"]," statement no longer needs to be morphed into something different by bundlers, but rather the browser now fully understands ",["code",null,"import"]," and can perform the request without the use of any bundler runtime. Module bundling logic can now be limited to build-time, rather than run-time, which reduces file size and puts module loading performance directly in the browser’s hands."],"\n",["p",null,"Bundlers are a valuable tool, and with the advancement of the standards, bundler runtime logic (the additional javascript executed by the user’s browser) may not be necessary in most cases. I say again: bundler ",["em",null,"runtime"]," logic. At build-time, bundlers are vital in being able to combine modules that should be grouped together into a single file. However, the output of a bundled file can now be in a pure ES Module format, and we can now let the browser’s high-optimized stack handle network requests, parsing, etc."],"\n",["h2",{"id":"predefining-the-web-component-library"},"Predefining the Web Component Library"],"\n",["p",null,"So with a large codebase slowing down an app’s initial startup, naturally the answer is stated with a simple “well just lazy load components then”. However, lazy loading components often enters a great deal of complexity of bundling, package.json and router configurations, custom framework logic built within each component and wrappers, and we’ve quickly lost the abilities of easily using a script tag. Alternatively, other lazy-load solutions require hardcoded HTML attribute values to go alongside even more custom runtime logic in order for the modules to be requested and wired up correctly."],"\n",["p",null,"With Stencil, one of its output targets is to define all of the components within the DOM, but the key is it does not require any of the component logic, and the predefined components are simply proxy components with no logic. In Stencil’s terms, an output target is able to take the developers source code and transform it into a highly optimized build. The compiler actually has a handful of output targets, but for now we’re focusing on the lazy-loading default."],"\n",["p",null,"With the lazy loading output target, once one of the components is added to DOM, the proxy component then requests and asynchronously wires up the component’s core logic to the host element on-demand. It’s important to note the entire architecture of the runtime allows the web components to be hydrated asynchronously, to include getting and setting properties, catching events before it’s been fully hydrated, and even ensure there is no flicker of the components before they’re loaded."],"\n",["p",null,"Further, Stencil performs static analysis of each component at build-time, and from this it already knows which components already work together, and should be bundled together. With this knowledge up front, the components are already built to avoid unnecessary HTTP requests, and each bundle request already comes with the component(s) it already knows it’ll require. On top of that, because components are now using the browser APIs to load modules, we’re able to take advantage of native ",["a",{"href":"https://developers.google.com/web/updates/2017/12/modulepreload"},"module preloading"]," without additional runtime or custom configuration."],"\n",["h2",{"id":"browser-driven-lazy-loading"},"Browser Driven Lazy-Loading"],"\n",["p",null,"With traditional setups, the developer usually has to take their best guess at build-time as to how components are going to be loaded by the end-user, and create their own entry modules through bundler configuration. With Stencil’s lazy-loading, all of the heavy lifting is placed directly on the browser, which already knows exactly which elements are in the DOM and is the best single source of truth since every end-user can navigate however they want. Instead of having end-users download additional JavaScript runtime to figure out which components should be loaded, and all that logic to do so, instead the browser tells us exactly which components are being used, and the browser performs the request itself."],"\n",["p",null,"How the element shows up in the DOM doesn’t actually matter; whether it was already within the HTML, rendered by Angular Ivy, ",["code",null,"React.createElement(‘ion-toggle’, null)"],", jQuery’s ",["code",null,"$(\"body\").append(\"\")"],", or even standard web APIs such ",["code",null,"document.createElement(‘ion-toggle’)"],"."],"\n",["p",null,"It doesn’t matter how the element came to be rendered in the DOM, either way, Stencil knows how to lazy-load itself using web-standards and native browser APIs. And by deferring most of the logic to the browser, rather than generating more JavaScript runtime, the components themselves have an optimal file size."],"\n",["p",null,"Aside from that, one of my favorite things to hear is how students are being taught web development with just Ionic. No framework, no build system. Just writing plain HTML and one script tag to access all of ",["a",{"href":"https://ionicframework.com/docs/components"},"Ionic's 100+ components"],", and have them lazy-load on-demand. All of this has been made easier due to Stencil’s architecture."],"\n",["p",null,"And for browsers that do not understand ES Modules and dynamic imports, Stencil also automatically generates ES5 builds with necessary polyfills that are only downloaded by browsers that require them (such as IE11)."],"\n",["h2",{"id":"focus-on-component-authoring-let-robots-do-everything-else"},"Focus On Component Authoring. Let Robots Do Everything Else."],"\n",["p",null,"Authoring, exporting, polyfilling, bundling, packaging, distributing, consuming, etc. are all complicated tasks, especially when trying to stay performant for the end-user. Tooling improves, frameworks update, bundlers change, and new APIs make old APIs obsolete. This especially holds true when your runtime framework decides to change how it works."],"\n",["p",null,"All those hundreds of components hardcoded to a specific runtime API must be rewritten yet again. The long list of “you must”, “never”, “don’t” and best practices change daily, when in the end we’re all just trying to happily build components for apps."],"\n",["p",null,"For all these reasons, this is one of the driving factors of why Stencil was created to help Ionic move quickly. Ionic core developers focus purely on creating and maintaining great looking components to be used within millions of apps. Stencil lets the core developers put their time into building components, while the robots are focused on optimizing everything else, and adjusting to new standards."],"\n",["h2",{"id":"conclusion"},"Conclusion"],"\n",["p",null,"Each framework and bundler has their own way to lazy load modules, and has its own way to be configured, which is great for innovation and new ideas, so we welcome each tool to do it their own way."],"\n",["p",null,"But with Ionic using Stencil’s lazy-loading abilities, which is actually just using native browser APIs, Ionic is able to free itself from each framework’s custom build system, tooling and changes. This helps to meet Ionic’s goal of providing a UI library for any framework, and any version of the framework, or no framework at all, all while generating components that sit atop web-standards. And while core developers can focus on component authoring and maintenance, the compiler can focus on the tasks of optimizing and bundling."],"\n",["p",null,"Hopefully this helps detail is more about how Stencil is addressing the goal of moving the complexity of easily distributing components into the build-time tooling, and let authoring and sharing components easy for developers, and fast for end-users."]]} \ No newline at end of file +{ + "title": "Stencil Blog - How Lazy-Loading Web Components Work with Stencil", + "date": "August 15, 2019", + "url": "/blog/how-lazy-loading-web-components-work", + "author": "Adam Bradley", + "twitter": "adamdbradley", + "description": "When you’re building an app that requires a large library of components in a single file download, you’re often forced to sacrifice performance - and specifically startup time - for the sake of accessing all those components. The two are often mutually exclusive. Choose to easily have all the components available, or choose blazing fast startup, but it’s difficult to get both. At least that’s the experience for many.", + "img": "/assets/img/blog/posts/stencil-lazy-loading.png", + "srcPath": "./src/blog/how-lazy-loading-works.md", + "hypertext": [ + "div", + null, + ["p", null, ["img", { "src": "/assets/img/blog/posts/stencil-lazy-loading.png", "alt": "Stencil Lazy Loading" }]], + "\n", + [ + "p", + null, + "When you’re building an app that requires a large library of components in a single file download, you’re often forced to sacrifice performance - and specifically startup time - for the sake of easily accessing all those components. The two are often mutually exclusive. Choose to have all the components available, or choose blazing fast startup, but it’s difficult to get both. At least that’s the experience for many." + ], + "\n", + [ + "p", + null, + "In fact, downloading and parsing a large set of JavaScript just to show the first page is where many apps struggle, and in many cases “lazy-loading” is a great solution to the problem. Lazy-loading is a term used for loading components only when the end-user requires it, which is a common technique used to speed-up app initialization." + ], + "\n", + [ + "p", + null, + "Stencil, a Web Component compiler used to build custom component libraries and design systems, was originally built for the ", + ["a", { "href": "https://ionicframework.com/" }, "Ionic Framework"], + ". And Ionic’s challenge has always been to easily distribute a large library of UI components, for both Material Design and iOS, while still staying performant and having a fast startup for Progressive Web Apps. In helping to solve the problem, Ionic moved to using Web Components, which can be distributed and consumed in numerous ways, each with their own pros and cons. But just using Web Components alone does not solve the startup and file size problem." + ], + "\n", + [ + "p", + null, + "We’re often asked “how” Stencil’s lazy loading works, and how one script can serve as a single entry point to a large library. But even further, why has Ionic migrated to this architecture, and how is it able to easily offer a large UI library without file size and startup penalties. In this article I’d like to describe a little further the reasoning behind each decision." + ], + "\n", + [ + "p", + null, + [ + "em", + null, + "Disclaimer: This is by no means claiming to be the one-true way to lazy load components. In fact there are many ways to lazy-load. This is how Stencil does it, and how Ionic components, developers and users have benefited using Stencil’s technique." + ] + ], + "\n", + ["h2", { "id": "script-tags-and-cdns" }, "Script Tags and CDNs"], + "\n", + [ + "p", + null, + "One of the simplest ways to use a web component is by adding its script tag to the webpage it’ll be used in. When the script loads, it automatically defines the custom element(s), and any custom element already on the page and any created thereafter on the page will get hydrated. Too easy right?" + ], + "\n", + [ + "p", + null, + "For a single component that works great. However, in Ionic’s case, or any large UI library or Design System for that matter, the challenge is that a single script containing every component is often far too large for an acceptable file size or app startup time." + ], + "\n", + [ + "p", + null, + "Even though the first paint may only use a handful of components, by bundling them all into one file the user is penalized by having to download the entire library ", + ["em", null, "before"], + " the user sees the app’s first page. This is thoroughly reviewed in ", + ["a", { "href": "https://v8.dev/blog/cost-of-javascript-2019" }, "The cost of JavaScript in 2019"], + " and definitely worth the time to read and digest." + ], + "\n", + [ + "p", + null, + [ + "em", + null, + "However, do note that Ionic and Stencil components can also be imported into traditional bundlers too. This post is reviewing how lazy-loading works when using the stand-alone script tag way." + ] + ], + "\n", + ["h2", { "id": "using-native-browser-features" }, "Using Native Browser Features"], + "\n", + [ + "p", + null, + "Luckily, browsers already ship with some extremely valuable, and somewhat lesser known, APIs that Ionic (using Stencil) is able to take advantage of. The biggest of those are native ", + ["a", { "href": "https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/" }, "ES Module imports"], + " and ", + [ + "a", + { + "href": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports" + }, + "dynamic imports" + ], + "." + ], + "\n", + [ + "p", + null, + "Traditionally within web development, we’ve become accustomed to source code getting transpiled into an unrecognizable ball of JavaScript, requiring the most finely tuned sourcemaps to make sense of it all. The most common of these is transforming the standardized ", + ["code", null, "import"], + " keyword into a deeply nested stack of callbacks in order for JavaScript “modules” to be loaded in an ES5 environment (such as IE11), by often reverting back to the non-standard ", + ["a", { "href": "https://en.wikipedia.org/wiki/CommonJS" }, "CommonJS"], + " format." + ], + "\n", + [ + "p", + null, + "With ES Modules now supported natively within browsers, the ", + ["code", null, "import"], + " statement no longer needs to be morphed into something different by bundlers, but rather the browser now fully understands ", + ["code", null, "import"], + " and can perform the request without the use of any bundler runtime. Module bundling logic can now be limited to build-time, rather than run-time, which reduces file size and puts module loading performance directly in the browser’s hands." + ], + "\n", + [ + "p", + null, + "Bundlers are a valuable tool, and with the advancement of the standards, bundler runtime logic (the additional javascript executed by the user’s browser) may not be necessary in most cases. I say again: bundler ", + ["em", null, "runtime"], + " logic. At build-time, bundlers are vital in being able to combine modules that should be grouped together into a single file. However, the output of a bundled file can now be in a pure ES Module format, and we can now let the browser’s high-optimized stack handle network requests, parsing, etc." + ], + "\n", + ["h2", { "id": "predefining-the-web-component-library" }, "Predefining the Web Component Library"], + "\n", + [ + "p", + null, + "So with a large codebase slowing down an app’s initial startup, naturally the answer is stated with a simple “well just lazy load components then”. However, lazy loading components often enters a great deal of complexity of bundling, package.json and router configurations, custom framework logic built within each component and wrappers, and we’ve quickly lost the abilities of easily using a script tag. Alternatively, other lazy-load solutions require hardcoded HTML attribute values to go alongside even more custom runtime logic in order for the modules to be requested and wired up correctly." + ], + "\n", + [ + "p", + null, + "With Stencil, one of its output targets is to define all of the components within the DOM, but the key is it does not require any of the component logic, and the predefined components are simply proxy components with no logic. In Stencil’s terms, an output target is able to take the developers source code and transform it into a highly optimized build. The compiler actually has a handful of output targets, but for now we’re focusing on the lazy-loading default." + ], + "\n", + [ + "p", + null, + "With the lazy loading output target, once one of the components is added to DOM, the proxy component then requests and asynchronously wires up the component’s core logic to the host element on-demand. It’s important to note the entire architecture of the runtime allows the web components to be hydrated asynchronously, to include getting and setting properties, catching events before it’s been fully hydrated, and even ensure there is no flicker of the components before they’re loaded." + ], + "\n", + [ + "p", + null, + "Further, Stencil performs static analysis of each component at build-time, and from this it already knows which components already work together, and should be bundled together. With this knowledge up front, the components are already built to avoid unnecessary HTTP requests, and each bundle request already comes with the component(s) it already knows it’ll require. On top of that, because components are now using the browser APIs to load modules, we’re able to take advantage of native ", + ["a", { "href": "https://developers.google.com/web/updates/2017/12/modulepreload" }, "module preloading"], + " without additional runtime or custom configuration." + ], + "\n", + ["h2", { "id": "browser-driven-lazy-loading" }, "Browser Driven Lazy-Loading"], + "\n", + [ + "p", + null, + "With traditional setups, the developer usually has to take their best guess at build-time as to how components are going to be loaded by the end-user, and create their own entry modules through bundler configuration. With Stencil’s lazy-loading, all of the heavy lifting is placed directly on the browser, which already knows exactly which elements are in the DOM and is the best single source of truth since every end-user can navigate however they want. Instead of having end-users download additional JavaScript runtime to figure out which components should be loaded, and all that logic to do so, instead the browser tells us exactly which components are being used, and the browser performs the request itself." + ], + "\n", + [ + "p", + null, + "How the element shows up in the DOM doesn’t actually matter; whether it was already within the HTML, rendered by Angular Ivy, ", + ["code", null, "React.createElement(‘ion-toggle’, null)"], + ", jQuery’s ", + ["code", null, "$(\"body\").append(\"\")"], + ", or even standard web APIs such ", + ["code", null, "document.createElement(‘ion-toggle’)"], + "." + ], + "\n", + [ + "p", + null, + "It doesn’t matter how the element came to be rendered in the DOM, either way, Stencil knows how to lazy-load itself using web-standards and native browser APIs. And by deferring most of the logic to the browser, rather than generating more JavaScript runtime, the components themselves have an optimal file size." + ], + "\n", + [ + "p", + null, + "Aside from that, one of my favorite things to hear is how students are being taught web development with just Ionic. No framework, no build system. Just writing plain HTML and one script tag to access all of ", + ["a", { "href": "https://ionicframework.com/docs/components" }, "Ionic's 100+ components"], + ", and have them lazy-load on-demand. All of this has been made easier due to Stencil’s architecture." + ], + "\n", + [ + "p", + null, + "And for browsers that do not understand ES Modules and dynamic imports, Stencil also automatically generates ES5 builds with necessary polyfills that are only downloaded by browsers that require them (such as IE11)." + ], + "\n", + [ + "h2", + { "id": "focus-on-component-authoring-let-robots-do-everything-else" }, + "Focus On Component Authoring. Let Robots Do Everything Else." + ], + "\n", + [ + "p", + null, + "Authoring, exporting, polyfilling, bundling, packaging, distributing, consuming, etc. are all complicated tasks, especially when trying to stay performant for the end-user. Tooling improves, frameworks update, bundlers change, and new APIs make old APIs obsolete. This especially holds true when your runtime framework decides to change how it works." + ], + "\n", + [ + "p", + null, + "All those hundreds of components hardcoded to a specific runtime API must be rewritten yet again. The long list of “you must”, “never”, “don’t” and best practices change daily, when in the end we’re all just trying to happily build components for apps." + ], + "\n", + [ + "p", + null, + "For all these reasons, this is one of the driving factors of why Stencil was created to help Ionic move quickly. Ionic core developers focus purely on creating and maintaining great looking components to be used within millions of apps. Stencil lets the core developers put their time into building components, while the robots are focused on optimizing everything else, and adjusting to new standards." + ], + "\n", + ["h2", { "id": "conclusion" }, "Conclusion"], + "\n", + [ + "p", + null, + "Each framework and bundler has their own way to lazy load modules, and has its own way to be configured, which is great for innovation and new ideas, so we welcome each tool to do it their own way." + ], + "\n", + [ + "p", + null, + "But with Ionic using Stencil’s lazy-loading abilities, which is actually just using native browser APIs, Ionic is able to free itself from each framework’s custom build system, tooling and changes. This helps to meet Ionic’s goal of providing a UI library for any framework, and any version of the framework, or no framework at all, all while generating components that sit atop web-standards. And while core developers can focus on component authoring and maintenance, the compiler can focus on the tasks of optimizing and bundling." + ], + "\n", + [ + "p", + null, + "Hopefully this helps detail is more about how Stencil is addressing the goal of moving the complexity of easily distributing components into the build-time tooling, and let authoring and sharing components easy for developers, and fast for end-users." + ] + ] +} diff --git a/static/blog/list.json b/static/blog/list.json index 60b260a41..ff4f3c688 100644 --- a/static/blog/list.json +++ b/static/blog/list.json @@ -19,4 +19,4 @@ "img": "/assets/img/blog/posts/stencil-lazy-loading.png", "filePath": "/assets/blog/how-lazy-loading-works.json" } -] \ No newline at end of file +] diff --git a/static/blog/stencil-roadmap-fall-2019.json b/static/blog/stencil-roadmap-fall-2019.json index 18579ac2a..78e248f17 100644 --- a/static/blog/stencil-roadmap-fall-2019.json +++ b/static/blog/stencil-roadmap-fall-2019.json @@ -1 +1,277 @@ -{"title":"Stencil Blog - Fall 2019 Stencil Roadmap","date":"August 28, 2019","url":"/blog/stencil-roadmap-fall-2019","author":"Adam Bradley","twitter":"adamdbradley","description":"With the Stencil One release behind us, we’re seeing developers build lots of successful Stencil-based web components. Now that the dust has settled, we realized it was time to talk about what’s next for the future of the project.","img":"/assets/img/blog/posts/stencil-roadmap-fall-2019.jpg","srcPath":"./src/blog/stencil-roadmap-fall-2019.md","hypertext":["div",null,["p",null,["img",{"src":"/assets/img/blog/posts/stencil-roadmap-fall-2019.jpg","alt":"Fall 2019 Stencil Roadmap"}]],"\n",["p",null,"With the ",["a",{"href":"https://ionicframework.com/blog/introducing-stencil-one-1-0-0/","rel":"noopener noreferrer","target":"_blank"},"Stencil One release"]," behind us, we’re seeing developers build lots of successful Stencil-based web components. Now that the dust has settled, we realized it was time to talk about what’s next for the future of the project."],"\n",["p",null,"From the very beginning, Stencil was built to directly meet ",["a",{"href":"https://ionicframework.com/docs","rel":"noopener noreferrer","target":"_blank"},"Ionic's"]," requirements, and we feel we’ve hit many of our original goals in generating a large UI library that can run in any framework, or no framework at all. ",["em",null,"Speaking of"],", the ",["a",{"href":"https://ionicframework.com/blog/announcing-ionic-react-release-candidate/","rel":"noopener noreferrer","target":"_blank"},"Ionic React release candidate was just published!"]],"\n",["p",null,"This isn’t to say we’re even close to “done”, since many more improvements can be made to developer experience, performance, build times, etc. As many large organizations have been adopting Stencil, we wanted to give a clear picture of where the project is going next."],"\n",["h2",{"id":"new-custom-element-output-target"},"New “Custom Element” Output Target"],"\n",["p",null,"By default, the Stencil compiler takes the developer’s source code and transforms it into ",["a",{"href":"/blog/how-lazy-loading-web-components-work","rel":"noopener noreferrer","target":"_blank"},"self lazy loading components"],". This was the original intent: making it easy to integrate into any project by ensuring that frameworks weren’t required and Ionic could be easily loaded from a CDN or script tag."],"\n",["p",null,"For Stencil, numerous output targets can be configured so developers, teams, and organizations can decide which build is best for their project, while always maintaining the original source code. Today, by default, only the lazy load output target is created."],"\n",["p",null,"However, we’re increasingly seeing a use case in which the Stencil compiler needs to export components as traditional ",["a",{"href":"https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements","rel":"noopener noreferrer","target":"_blank"},"custom elements"]," (i.e., extending ",["code",null,"HTMLElement"],") that can also lazy load themselves without a framework. The output target would not self define the components, so it’s up to the module that imports the custom element to ",["a",{"href":"https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define","rel":"noopener noreferrer","target":"_blank"},"define"]," it."],"\n",["p",null,"What we’re really excited about is that any new output targets do not require any refactoring on the developers end, and the original source code can stay the same. Expect more on this new output target soon."],"\n",["h2",{"id":"design-system-tooling-and-documentation"},"Design System Tooling and Documentation"],"\n",["p",null,"An area we’re looking to further improve is being able to generate ",["a",{"href":"https://stenciljs.com/docs/stencil-for-design-systems","rel":"noopener noreferrer","target":"_blank"},"design systems"]," that scale for numerous teams and projects. As you’ve guessed it, Ionic is already using a lot of Stencil’s tooling to generate the ",["a",{"href":"https://ionicframework.com/docs/api/button","rel":"noopener noreferrer","target":"_blank"},"Ionic Documentation"]," site. But there’s so much more to improve upon. Most of these features will be very specific to teams building actual design systems but one key feature we have been getting asked for is an isolated environment for developing components."],"\n",["p",null,"You will soon be able to develop a component in an environment that is isolated from the rest of your application. Part of the tooling will allow you to specify multiple component states so that you can see many example states while developing your component."],"\n",["h2",{"id":"public-compiler-apis"},"Public Compiler APIs"],"\n",["p",null,"Another area we’re also focusing on is ensuring the compiler can work within a browser and used by other tools. We’ve already been working with a few awesome teams such as ",["a",{"href":"https://stackblitz.com/","rel":"noopener noreferrer","target":"_blank"},"Stackblitz"],", ",["a",{"href":"https://codesandbox.io/","rel":"noopener noreferrer","target":"_blank"},"CodeSandbox"],", and ",["a",{"href":"","rel":"noopener noreferrer","target":"_blank"}],["a",{"href":"https://webcomponents.dev/"},"WebComponents.dev"],". At the lowest levels, the compiler already works without running atop a ",["a",{"href":"https://nodejs.org/","rel":"noopener noreferrer","target":"_blank"},"NodeJS"]," environment, so technically this isn’t a major refactor, but more-so just exposing the correct APIs."],"\n",["p",null,"We’re also seeing many areas for improvement to ensure the compiler is easy to consume by other NodeJS tools, including ",["a",{"href":"https://rollupjs.org/","rel":"noopener noreferrer","target":"_blank"},"Rollup"],", ",["a",{"href":"https://parceljs.org/","rel":"noopener noreferrer","target":"_blank"},"Parcel"],", ",["a",{"href":"https://webpack.js.org/","rel":"noopener noreferrer","target":"_blank"},"WebPack"],", and ",["a",{"href":"https://bazel.build/","rel":"noopener noreferrer","target":"_blank"},"Bazel"],". If you’re a maintainer of any tooling, whether an online tool or a NodeJS environment, and you’re looking to implement the Stencil compiler, ",["a",{"href":"https://chat.stenciljs.com/","rel":"noopener noreferrer","target":"_blank"},"please feel free to reach out"]," and we’ll be happy to help!"],"\n",["h2",{"id":"component-asset-management"},"Component Asset Management"],"\n",["p",null,"A common challenge with components is not only improving shareability among developers, but also easily sharing all of the static assets a component may use. For example, if a component is using a static image in a development environment, it’s relatively straightforward to point the url directly to the image. However, once you deploy the component(s) to a CDN, or ",["a",{"href":"https://www.npmjs.com/","rel":"noopener noreferrer","target":"_blank"},"npm"],", or an internal network, etc., the direct URL path to that image becomes more of a challenge."],"\n",["p",null,"With ",["a",{"href":"https://ionic.io/ionicons","target":"_blank"},"Ionicons"],", we’re using Stencil’s ",["code",null,"getAssetPath()"]," API, which is where we’ll put more time into documenting and detailing best practices for loading static assets within components."],"\n",["h2",{"id":"web-workers"},"Web Workers"],"\n",["p",null,"An exciting area we’ll start putting more time into is increased utilization of ",["a",{"href":"https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers","rel":"noopener noreferrer","target":"_blank"},"web workers"],". As it stands, developers can already implement web workers within Stencil components today (they’re just another web API, after all)."],"\n",["p",null,"However, from the very beginning, the Stencil runtime was designed to be asynchronous, meaning that every component can communicate with the outside world without having to be synchronously tied to one another. With traditional component models, this isn’t always true. Stencil’s asynchronous nature offers some great advantages for not only lazy loading and performance, but for web workers too!"],"\n",["p",null,"Stencil components are not directly wired up to the DOM, and even DOM updates are scheduled in an asynchronous queue. This means that the entire component runtime and logic can live instead within a web worker, thus dedicating the main thread to focusing only on updating the DOM. A new output target could be built to automatically generate this form of components. There’s a lot more to be researched here, but it’s an area we’re very excited about because it could offer some amazing performance implications."],"\n",["h2",{"id":"source-maps"},"Source Maps"],"\n",["p",null,"One major benefit of using native ",["a",{"href":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import","rel":"noopener noreferrer","target":"_blank"},"JavaScript modules and imports"]," is that the original source code is largely left untouched. Granted, TypeScript removes the types and Stencil removes the decorators, but the developer’s original source code is largely as-is."],"\n",["p",null,"Because of this, we focused our development time into different areas while Stencil was initially being developed. However, we recognize that source maps improve debugging and testing, so we’ll ensure they line up correctly in upcoming versions."],"\n",["h2",{"id":"conclusion"},"Conclusion"],"\n",["p",null,"We’re really happy with Stencil’s reception so far, but there’s still much more we can do to improve the developer experience and make it easier to build and maintain a large component library. The above represent our current ideas and goals, which may change as we head into 2020. That said, please feel free to swing by the ",["a",{"href":"https://chat.stenciljs.com/","rel":"noopener noreferrer","target":"_blank"},"discord channel"]," to share any feedback you have. As always, ",["a",{"href":"https://github.com/ionic-team/stencil","rel":"noopener noreferrer","target":"_blank"},"contributions to the project"]," are welcome too!"],"\n",["p",null,"Happy coding!"]]} \ No newline at end of file +{ + "title": "Stencil Blog - Fall 2019 Stencil Roadmap", + "date": "August 28, 2019", + "url": "/blog/stencil-roadmap-fall-2019", + "author": "Adam Bradley", + "twitter": "adamdbradley", + "description": "With the Stencil One release behind us, we’re seeing developers build lots of successful Stencil-based web components. Now that the dust has settled, we realized it was time to talk about what’s next for the future of the project.", + "img": "/assets/img/blog/posts/stencil-roadmap-fall-2019.jpg", + "srcPath": "./src/blog/stencil-roadmap-fall-2019.md", + "hypertext": [ + "div", + null, + [ + "p", + null, + ["img", { "src": "/assets/img/blog/posts/stencil-roadmap-fall-2019.jpg", "alt": "Fall 2019 Stencil Roadmap" }] + ], + "\n", + [ + "p", + null, + "With the ", + [ + "a", + { + "href": "https://ionicframework.com/blog/introducing-stencil-one-1-0-0/", + "rel": "noopener noreferrer", + "target": "_blank" + }, + "Stencil One release" + ], + " behind us, we’re seeing developers build lots of successful Stencil-based web components. Now that the dust has settled, we realized it was time to talk about what’s next for the future of the project." + ], + "\n", + [ + "p", + null, + "From the very beginning, Stencil was built to directly meet ", + ["a", { "href": "https://ionicframework.com/docs", "rel": "noopener noreferrer", "target": "_blank" }, "Ionic's"], + " requirements, and we feel we’ve hit many of our original goals in generating a large UI library that can run in any framework, or no framework at all. ", + ["em", null, "Speaking of"], + ", the ", + [ + "a", + { + "href": "https://ionicframework.com/blog/announcing-ionic-react-release-candidate/", + "rel": "noopener noreferrer", + "target": "_blank" + }, + "Ionic React release candidate was just published!" + ] + ], + "\n", + [ + "p", + null, + "This isn’t to say we’re even close to “done”, since many more improvements can be made to developer experience, performance, build times, etc. As many large organizations have been adopting Stencil, we wanted to give a clear picture of where the project is going next." + ], + "\n", + ["h2", { "id": "new-custom-element-output-target" }, "New “Custom Element” Output Target"], + "\n", + [ + "p", + null, + "By default, the Stencil compiler takes the developer’s source code and transforms it into ", + [ + "a", + { "href": "/blog/how-lazy-loading-web-components-work", "rel": "noopener noreferrer", "target": "_blank" }, + "self lazy loading components" + ], + ". This was the original intent: making it easy to integrate into any project by ensuring that frameworks weren’t required and Ionic could be easily loaded from a CDN or script tag." + ], + "\n", + [ + "p", + null, + "For Stencil, numerous output targets can be configured so developers, teams, and organizations can decide which build is best for their project, while always maintaining the original source code. Today, by default, only the lazy load output target is created." + ], + "\n", + [ + "p", + null, + "However, we’re increasingly seeing a use case in which the Stencil compiler needs to export components as traditional ", + [ + "a", + { + "href": "https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements", + "rel": "noopener noreferrer", + "target": "_blank" + }, + "custom elements" + ], + " (i.e., extending ", + ["code", null, "HTMLElement"], + ") that can also lazy load themselves without a framework. The output target would not self define the components, so it’s up to the module that imports the custom element to ", + [ + "a", + { + "href": "https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define", + "rel": "noopener noreferrer", + "target": "_blank" + }, + "define" + ], + " it." + ], + "\n", + [ + "p", + null, + "What we’re really excited about is that any new output targets do not require any refactoring on the developers end, and the original source code can stay the same. Expect more on this new output target soon." + ], + "\n", + ["h2", { "id": "design-system-tooling-and-documentation" }, "Design System Tooling and Documentation"], + "\n", + [ + "p", + null, + "An area we’re looking to further improve is being able to generate ", + [ + "a", + { + "href": "https://stenciljs.com/docs/stencil-for-design-systems", + "rel": "noopener noreferrer", + "target": "_blank" + }, + "design systems" + ], + " that scale for numerous teams and projects. As you’ve guessed it, Ionic is already using a lot of Stencil’s tooling to generate the ", + [ + "a", + { "href": "https://ionicframework.com/docs/api/button", "rel": "noopener noreferrer", "target": "_blank" }, + "Ionic Documentation" + ], + " site. But there’s so much more to improve upon. Most of these features will be very specific to teams building actual design systems but one key feature we have been getting asked for is an isolated environment for developing components." + ], + "\n", + [ + "p", + null, + "You will soon be able to develop a component in an environment that is isolated from the rest of your application. Part of the tooling will allow you to specify multiple component states so that you can see many example states while developing your component." + ], + "\n", + ["h2", { "id": "public-compiler-apis" }, "Public Compiler APIs"], + "\n", + [ + "p", + null, + "Another area we’re also focusing on is ensuring the compiler can work within a browser and used by other tools. We’ve already been working with a few awesome teams such as ", + ["a", { "href": "https://stackblitz.com/", "rel": "noopener noreferrer", "target": "_blank" }, "Stackblitz"], + ", ", + ["a", { "href": "https://codesandbox.io/", "rel": "noopener noreferrer", "target": "_blank" }, "CodeSandbox"], + ", and ", + ["a", { "href": "", "rel": "noopener noreferrer", "target": "_blank" }], + ["a", { "href": "https://webcomponents.dev/" }, "WebComponents.dev"], + ". At the lowest levels, the compiler already works without running atop a ", + ["a", { "href": "https://nodejs.org/", "rel": "noopener noreferrer", "target": "_blank" }, "NodeJS"], + " environment, so technically this isn’t a major refactor, but more-so just exposing the correct APIs." + ], + "\n", + [ + "p", + null, + "We’re also seeing many areas for improvement to ensure the compiler is easy to consume by other NodeJS tools, including ", + ["a", { "href": "https://rollupjs.org/", "rel": "noopener noreferrer", "target": "_blank" }, "Rollup"], + ", ", + ["a", { "href": "https://parceljs.org/", "rel": "noopener noreferrer", "target": "_blank" }, "Parcel"], + ", ", + ["a", { "href": "https://webpack.js.org/", "rel": "noopener noreferrer", "target": "_blank" }, "WebPack"], + ", and ", + ["a", { "href": "https://bazel.build/", "rel": "noopener noreferrer", "target": "_blank" }, "Bazel"], + ". If you’re a maintainer of any tooling, whether an online tool or a NodeJS environment, and you’re looking to implement the Stencil compiler, ", + [ + "a", + { "href": "https://chat.stenciljs.com/", "rel": "noopener noreferrer", "target": "_blank" }, + "please feel free to reach out" + ], + " and we’ll be happy to help!" + ], + "\n", + ["h2", { "id": "component-asset-management" }, "Component Asset Management"], + "\n", + [ + "p", + null, + "A common challenge with components is not only improving shareability among developers, but also easily sharing all of the static assets a component may use. For example, if a component is using a static image in a development environment, it’s relatively straightforward to point the url directly to the image. However, once you deploy the component(s) to a CDN, or ", + ["a", { "href": "https://www.npmjs.com/", "rel": "noopener noreferrer", "target": "_blank" }, "npm"], + ", or an internal network, etc., the direct URL path to that image becomes more of a challenge." + ], + "\n", + [ + "p", + null, + "With ", + ["a", { "href": "https://ionic.io/ionicons", "target": "_blank" }, "Ionicons"], + ", we’re using Stencil’s ", + ["code", null, "getAssetPath()"], + " API, which is where we’ll put more time into documenting and detailing best practices for loading static assets within components." + ], + "\n", + ["h2", { "id": "web-workers" }, "Web Workers"], + "\n", + [ + "p", + null, + "An exciting area we’ll start putting more time into is increased utilization of ", + [ + "a", + { + "href": "https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers", + "rel": "noopener noreferrer", + "target": "_blank" + }, + "web workers" + ], + ". As it stands, developers can already implement web workers within Stencil components today (they’re just another web API, after all)." + ], + "\n", + [ + "p", + null, + "However, from the very beginning, the Stencil runtime was designed to be asynchronous, meaning that every component can communicate with the outside world without having to be synchronously tied to one another. With traditional component models, this isn’t always true. Stencil’s asynchronous nature offers some great advantages for not only lazy loading and performance, but for web workers too!" + ], + "\n", + [ + "p", + null, + "Stencil components are not directly wired up to the DOM, and even DOM updates are scheduled in an asynchronous queue. This means that the entire component runtime and logic can live instead within a web worker, thus dedicating the main thread to focusing only on updating the DOM. A new output target could be built to automatically generate this form of components. There’s a lot more to be researched here, but it’s an area we’re very excited about because it could offer some amazing performance implications." + ], + "\n", + ["h2", { "id": "source-maps" }, "Source Maps"], + "\n", + [ + "p", + null, + "One major benefit of using native ", + [ + "a", + { + "href": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import", + "rel": "noopener noreferrer", + "target": "_blank" + }, + "JavaScript modules and imports" + ], + " is that the original source code is largely left untouched. Granted, TypeScript removes the types and Stencil removes the decorators, but the developer’s original source code is largely as-is." + ], + "\n", + [ + "p", + null, + "Because of this, we focused our development time into different areas while Stencil was initially being developed. However, we recognize that source maps improve debugging and testing, so we’ll ensure they line up correctly in upcoming versions." + ], + "\n", + ["h2", { "id": "conclusion" }, "Conclusion"], + "\n", + [ + "p", + null, + "We’re really happy with Stencil’s reception so far, but there’s still much more we can do to improve the developer experience and make it easier to build and maintain a large component library. The above represent our current ideas and goals, which may change as we head into 2020. That said, please feel free to swing by the ", + [ + "a", + { "href": "https://chat.stenciljs.com/", "rel": "noopener noreferrer", "target": "_blank" }, + "discord channel" + ], + " to share any feedback you have. As always, ", + [ + "a", + { "href": "https://github.com/ionic-team/stencil", "rel": "noopener noreferrer", "target": "_blank" }, + "contributions to the project" + ], + " are welcome too!" + ], + "\n", + ["p", null, "Happy coding!"] + ] +} diff --git a/static/cli.ts b/static/cli.ts index 11bfe7054..e50d86ce9 100644 --- a/static/cli.ts +++ b/static/cli.ts @@ -1,2 +1,2 @@ -console.log('\x1b[31mERROR\x1b[0m Stencil for Deno has reached end-of-life') +console.log('\x1b[31mERROR\x1b[0m Stencil for Deno has reached end-of-life'); Deno.exit(1); diff --git a/static/docs-structure.json b/static/docs-structure.json index 80a33e6ea..bb478fb68 100644 --- a/static/docs-structure.json +++ b/static/docs-structure.json @@ -445,4 +445,4 @@ } ] } -] \ No newline at end of file +]