chore: apply prettier to all *.md files

This commit is contained in:
Thomas Allmer
2019-10-24 00:59:49 +02:00
parent 407baa11b4
commit 1cda471818
50 changed files with 837 additions and 552 deletions

View File

@@ -31,7 +31,7 @@ Make your changes to the project. Commits are linted using precommit hooks, mean
# Committing Your Changes
Open WC uses [commitlint](https://github.com/marionebl/commitlint) to standardize commit messages in the project. Commit messages must follow the [conventional commit format](https://www.conventionalcommits.org/en/v1.0.0-beta.2/)
Open WC uses package name as scope. So for example if you fix a *terrible bug* in the package `@open-wc/testing`, the commit message should look like this:
Open WC uses package name as scope. So for example if you fix a _terrible bug_ in the package `@open-wc/testing`, the commit message should look like this:
```
fix(testing): fix terrible bug

View File

@@ -1,6 +1,7 @@
<p align="center"><img src="https://github.com/open-wc/open-wc/blob/master/assets/images/logo.png" width="200" alt="Open-wc Logo" /></p>
# Open Web Component Recommendations
Open Web Components provides a set of defaults, recommendations and tools to help facilitate your web component project. Our recommendations include: developing, linting, testing, building, tooling, demoing, publishing and automating.
[![CircleCI](https://circleci.com/gh/open-wc/open-wc.svg?style=shield)](https://circleci.com/gh/open-wc/open-wc)
@@ -8,6 +9,7 @@ Open Web Components provides a set of defaults, recommendations and tools to hel
[![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/)
## Usage
```bash
# in a new or existing folder:
npm init @open-wc
@@ -15,6 +17,7 @@ npm init @open-wc
```
This will kickstart a menu guiding you through all available actions.
```
$ npm init @open-wc
npx: installed 14 in 4.074s
@@ -25,44 +28,46 @@ What would you like to do today?
```
## Homepage
For more details please visit us at [open-wc.org](https://open-wc.org).
## Packages
| Package | Version | Description |
|------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [building-rollup](./packages/building-rollup) | [![building-rollup](https://img.shields.io/npm/v/@open-wc/building-rollup.svg)](https://www.npmjs.com/package/@open-wc/building-rollup) | Default configuration for working with rollup. |
| [building-webpack](./packages/building-webpack) | [![building-webpack](https://img.shields.io/npm/v/@open-wc/building-webpack.svg)](https://www.npmjs.com/package/@open-wc/building-webpack) | Default configuration for working with webpack. |
| [chai-dom-equals](./packages/chai-dom-equals) | [![chai-dom-equals](https://img.shields.io/npm/v/@open-wc/chai-dom-equals.svg)](https://www.npmjs.com/package/@open-wc/chai-dom-equals) | Chai Plugin to compare dom and shadow dom trees. Part of open-wc recommendations. |
| [create](./packages/create) | [![create](https://img.shields.io/npm/v/@open-wc/create.svg)](https://www.npmjs.com/package/@open-wc/create) | Scaffold web components following open-wc recommendations. |
| [demoing-storybook](./packages/demoing-storybook) | [![demoing-storybook](https://img.shields.io/npm/v/@open-wc/demoing-storybook.svg)](https://www.npmjs.com/package/@open-wc/demoing-storybook) | Storybook configuration following open-wc recommendations. |
| [eslint-config](./packages/eslint-config) | [![eslint-config](https://img.shields.io/npm/v/@open-wc/eslint-config.svg)](https://www.npmjs.com/package/@open-wc/eslint-config) | Eslint configuration following open-wc recommendations. |
| [es-dev-server](./packages/es-dev-server) | [![es-dev-server](https://img.shields.io/npm/v/es-dev-server.svg)](https://www.npmjs.com/package/es-dev-server) | Development server for modern web apps. |
| [polyfills-loader](./packages/polyfills-loader) | [![polyfills-loader](https://img.shields.io/npm/v/@open-wc/polyfills-loader.svg)](https://www.npmjs.com/package/@open-wc/polyfills-loader) | Load web component polyfills using dynamic imports. |
| [prettier-config](./packages/prettier-config) | [![prettier-config](https://img.shields.io/npm/v/@open-wc/prettier-config.svg)](https://www.npmjs.com/package/@open-wc/prettier-config) | Prettier configuration following open-wc recommendations. |
| [semantic-dom-diff](./packages/semantic-dom-diff) | [![semantic-dom-diff](https://img.shields.io/npm/v/@open-wc/semantic-dom-diff.svg)](https://www.npmjs.com/package/@open-wc/semantic-dom-diff) | To compare dom and shadow dom trees. Part of open-wc recommendations. |
| [testing](./packages/testing) | [![testing](https://img.shields.io/npm/v/@open-wc/testing.svg)](https://www.npmjs.com/package/@open-wc/testing) | Testing following open-wc recommendations. |
| [testing-helpers](./packages/testing-helpers) | [![testing-helpers](https://img.shields.io/npm/v/@open-wc/testing-helpers.svg)](https://www.npmjs.com/package/@open-wc/testing-helpers) | Testing Helpers following open-wc recommendations. |
| [testing-karma](./packages/testing-karma) | [![testing-karma](https://img.shields.io/npm/v/@open-wc/testing-karma.svg)](https://www.npmjs.com/package/@open-wc/testing-karma) | Testing with Karma following open-wc recommendations. |
| [testing-karma-bs](./packages/testing-karma-bs) | [![testing-karma-bs](https://img.shields.io/npm/v/@open-wc/testing-karma-bs.svg)](https://www.npmjs.com/package/@open-wc/testing-karma-bs) | Testing with Karma using Browserstack following open-wc recommendations. |
| [testing-wallaby](./packages/testing-wallaby) | [![testing-wallaby](https://img.shields.io/npm/v/@open-wc/testing-wallaby.svg)](https://www.npmjs.com/package/@open-wc/testing-wallaby) | Testing with wallaby following open-wc recommendations. |
| [webpack-import-meta-loader](./packages/webpack-import-meta-loader) | [![webpack-import-meta-loader](https://img.shields.io/npm/v/@open-wc/webpack-import-meta-loader.svg)](https://www.npmjs.com/package/@open-wc/webpack-import-meta-loader) | Webpack loader plugin to support import.meta. |
| Package | Version | Description |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
| [building-rollup](./packages/building-rollup) | [![building-rollup](https://img.shields.io/npm/v/@open-wc/building-rollup.svg)](https://www.npmjs.com/package/@open-wc/building-rollup) | Default configuration for working with rollup. |
| [building-webpack](./packages/building-webpack) | [![building-webpack](https://img.shields.io/npm/v/@open-wc/building-webpack.svg)](https://www.npmjs.com/package/@open-wc/building-webpack) | Default configuration for working with webpack. |
| [chai-dom-equals](./packages/chai-dom-equals) | [![chai-dom-equals](https://img.shields.io/npm/v/@open-wc/chai-dom-equals.svg)](https://www.npmjs.com/package/@open-wc/chai-dom-equals) | Chai Plugin to compare dom and shadow dom trees. Part of open-wc recommendations. |
| [create](./packages/create) | [![create](https://img.shields.io/npm/v/@open-wc/create.svg)](https://www.npmjs.com/package/@open-wc/create) | Scaffold web components following open-wc recommendations. |
| [demoing-storybook](./packages/demoing-storybook) | [![demoing-storybook](https://img.shields.io/npm/v/@open-wc/demoing-storybook.svg)](https://www.npmjs.com/package/@open-wc/demoing-storybook) | Storybook configuration following open-wc recommendations. |
| [eslint-config](./packages/eslint-config) | [![eslint-config](https://img.shields.io/npm/v/@open-wc/eslint-config.svg)](https://www.npmjs.com/package/@open-wc/eslint-config) | Eslint configuration following open-wc recommendations. |
| [es-dev-server](./packages/es-dev-server) | [![es-dev-server](https://img.shields.io/npm/v/es-dev-server.svg)](https://www.npmjs.com/package/es-dev-server) | Development server for modern web apps. |
| [polyfills-loader](./packages/polyfills-loader) | [![polyfills-loader](https://img.shields.io/npm/v/@open-wc/polyfills-loader.svg)](https://www.npmjs.com/package/@open-wc/polyfills-loader) | Load web component polyfills using dynamic imports. |
| [prettier-config](./packages/prettier-config) | [![prettier-config](https://img.shields.io/npm/v/@open-wc/prettier-config.svg)](https://www.npmjs.com/package/@open-wc/prettier-config) | Prettier configuration following open-wc recommendations. |
| [semantic-dom-diff](./packages/semantic-dom-diff) | [![semantic-dom-diff](https://img.shields.io/npm/v/@open-wc/semantic-dom-diff.svg)](https://www.npmjs.com/package/@open-wc/semantic-dom-diff) | To compare dom and shadow dom trees. Part of open-wc recommendations. |
| [testing](./packages/testing) | [![testing](https://img.shields.io/npm/v/@open-wc/testing.svg)](https://www.npmjs.com/package/@open-wc/testing) | Testing following open-wc recommendations. |
| [testing-helpers](./packages/testing-helpers) | [![testing-helpers](https://img.shields.io/npm/v/@open-wc/testing-helpers.svg)](https://www.npmjs.com/package/@open-wc/testing-helpers) | Testing Helpers following open-wc recommendations. |
| [testing-karma](./packages/testing-karma) | [![testing-karma](https://img.shields.io/npm/v/@open-wc/testing-karma.svg)](https://www.npmjs.com/package/@open-wc/testing-karma) | Testing with Karma following open-wc recommendations. |
| [testing-karma-bs](./packages/testing-karma-bs) | [![testing-karma-bs](https://img.shields.io/npm/v/@open-wc/testing-karma-bs.svg)](https://www.npmjs.com/package/@open-wc/testing-karma-bs) | Testing with Karma using Browserstack following open-wc recommendations. |
| [testing-wallaby](./packages/testing-wallaby) | [![testing-wallaby](https://img.shields.io/npm/v/@open-wc/testing-wallaby.svg)](https://www.npmjs.com/package/@open-wc/testing-wallaby) | Testing with wallaby following open-wc recommendations. |
| [webpack-import-meta-loader](./packages/webpack-import-meta-loader) | [![webpack-import-meta-loader](https://img.shields.io/npm/v/@open-wc/webpack-import-meta-loader.svg)](https://www.npmjs.com/package/@open-wc/webpack-import-meta-loader) | Webpack loader plugin to support import.meta. |
## Contact
Feel free to reach out to us on [twitter](https://twitter.com/OpenWc) or create [a github issue](https://github.com/open-wc/open-wc/issues/new) for any feedback or questions you might have.
You can also find us on the Polymer slack in the [#open-wc](https://polymer.slack.com/messages/CE6D9DN05) channel.
You can join the Polymer slack by visiting [https://www.polymer-project.org/slack-invite](https://www.polymer-project.org/slack-invite).
## We Proudly Use
<a href="http://browserstack.com/" style="border: none;"><img src="https://github.com/open-wc/open-wc/blob/master/assets/images/Browserstack-logo.svg" width="200" alt="Browserstack Logo" /></a>
<a href="http://netlify.com/" style="border: none;"><img src="https://www.netlify.com/img/press/logos/full-logo-light.svg" width="185" alt="netlify logo" /></a>
## Guide
```bash
# bootstrap/setup
yarn install

View File

@@ -4,14 +4,15 @@ heroImage: /hero.png
actionText: Get Started →
actionLink: /guide/
features:
- title: Smart Defaults
details: Enjoy the peace of mind that comes from having a well-known default solution for almost everything. From linting to testing to demos to publishing - have the full experience.
- title: Awesome Generators
details: Get up and running quickly with opinionated generators, or add recommended tools to existing projects. Our comprehensive fleet of generators have got you covered.
- title: Open Source Love
details: Open Web Components is a community-effort, independent of any framework or company. We use mostly open-source tools and services.
- title: Smart Defaults
details: Enjoy the peace of mind that comes from having a well-known default solution for almost everything. From linting to testing to demos to publishing - have the full experience.
- title: Awesome Generators
details: Get up and running quickly with opinionated generators, or add recommended tools to existing projects. Our comprehensive fleet of generators have got you covered.
- title: Open Source Love
details: Open Web Components is a community-effort, independent of any framework or company. We use mostly open-source tools and services.
footer: MIT Licensed | Copyright © 2018-2019 open-wc
---
<hr>
<p align="center" style="margin: 50px; color: #4e6e8e;">
<q><i>I used open-wc to get testing working, it was so helpful, works like a charm!</i></q>

View File

@@ -23,7 +23,7 @@ Many web developers have experienced the dreaded "Javascript Fatigue". With our
We want web component development to be accessible and approachable for everyone, regardless of their background. Therefore, our recommendations aim to be easy to use, be ready to use, and provide that "it just works" developer experience we all crave for the various aspects of web component development.
Best practices/recommendations and examples may change and evolve over time.
Best practices/recommendations and examples may change and evolve over time.
### Why Web Components
@@ -46,12 +46,15 @@ What if you could remove code, gain performance, and streamline implementation a
- Write using a streamlined component API that combines the best bits of popular libraries and frameworks!
##### Performance
Just like `querySelector` reduces developers' dependence on jQuery, the web components standards reduces the size and complexity of component libraries and frameworks. This ultimately benefits users by decreasing page load times and increasing app performance.
##### Future Proofing
Using the browser's standards-based component model will increase the longevity of your application. The web has an extremely strong tradition of backwards-compatibility. Standards bodies have consistently gone out of their way to maintain legacy APIs.
##### Flexibility
The web components standards are fairly low-level, letting library authors build upon them with innovative APIs. By using such libraries you can build your app in the style you want while still leveraging built-in browser features.
## Contribute

View File

@@ -1,10 +1,10 @@
# Blog
## [Announcing Open Web Components](https://dev.to/thepassle/announcing-open-web-components-5h7)
## [Announcing Open Web Components](https://dev.to/thepassle/announcing-open-web-components-5h7)
by [open-wc](https://github.com/open-wc)
## [Cross Browser Testing your Stencil Web Component like a boss](https://medium.com/vincent-ogloblinsky/cross-browser-testing-your-stencil-web-component-like-a-boss-93c1b154bfd9)
## [Cross Browser Testing your Stencil Web Component like a boss](https://medium.com/vincent-ogloblinsky/cross-browser-testing-your-stencil-web-component-like-a-boss-93c1b154bfd9)
by [Vincent Ogloblinsky](https://github.com/vogloblinsky)
@@ -12,10 +12,10 @@ by [Vincent Ogloblinsky](https://github.com/vogloblinsky)
by [npm](npmjs.com)
## [Not Another To Do App](https://medium.com/@westbrook/not-another-to-do-app-169c14bb7ef9)
## [Not Another To Do App](https://medium.com/@westbrook/not-another-to-do-app-169c14bb7ef9)
by [Westbrook Johnson](https://github.com/westbrook)
## [Web Components: spoils of the browser wars](https://www.andrewzigler.com/blog/2019/02/28/web-components-spoils-of-the-browser-wars/)
## [Web Components: spoils of the browser wars](https://www.andrewzigler.com/blog/2019/02/28/web-components-spoils-of-the-browser-wars/)
by [Andrew Zigler](https://github.com/azigler)

View File

@@ -10,7 +10,6 @@ This is such a powerful and widely-used pattern in the current JavaScript ecosys
We want to help you build your apps as easily and efficiently as possible, so for now we've adopted this practice as our only exception to the above rules.
The [import maps](https://github.com/WICG/import-maps) proposal aims to bring bare modules to the web browser. You can follow that repository to stay up to date.
## Workflows
We recommend implementing the following three workflows for specific tasks while developing your component or application.
@@ -26,9 +25,11 @@ We recommend our [ES Dev Server](../developing/es-dev-server.html) as it does no
:::
When would you choose this workflow:
- When developing new features
Why would you choose this:
- Simple to setup
- As fast as it gets
@@ -38,16 +39,17 @@ Chances are that the web components you're building will need to run in more tha
In these cases it's time to open your toolbox and make sure everything works in all supported browsers.
When would you choose this workflow:
- To verify everything works in all supported browsers
- To debug legacy browsers
We recommend our [Open Web Components Building Setup](../building).
Why would you choose it:
- As good as it gets when you need to work with legacy browsers
- Auto-bundling/reloading
### Production Workflow
Once you're happy with your web components, it's time to put them somewhere more useful.
@@ -55,11 +57,13 @@ Most likely a publicly available web server.
Before you do that let's apply all the optimizations magic we can cook up.
When would you use this:
- Optimize your build
- Publishing to production
We recommend our [Open Web Components Building Setup](../building).
Why would you choose it:
- Multiple bundles for differential serving
- Conditional auto-loader for those bundles (without a special server)

View File

@@ -3,6 +3,7 @@
Having continuous integration in your project can provide valuable insights, and we consider it an essential in your projects.
## Circle ci
If you use the default generator you will already have CircleCi setup with a .circleci folder.
It also contains a config that takes care of linting and testing.
@@ -11,13 +12,14 @@ This is part of the default [open-wc](https://open-wc.org/) recommendation.
:::
## Setup
```bash
npm init @open-wc automating
```
### Manual Setup
- copy [.circleci/config.yml](https://github.com/open-wc/open-wc/blob/master/packages/create/src/generators/tools-circleci/templates/static/.circleci/config.yml) to `.circleci/config.yml`
- copy [.circleci/config.yml](https://github.com/open-wc/open-wc/blob/master/packages/create/src/generators/tools-circleci/templates/static/.circleci/config.yml) to `.circleci/config.yml`
## Usage
@@ -36,5 +38,5 @@ npm init @open-wc automating
- Look for "Automate", and write down the "Access Key" and "Username"
- Open your [circleci App](https://circleci.com/dashboard) or direclty via https://circleci.com/gh/{groupname}/{reponame}/edit
- Go to the project settings -> Environment Variables
- Add Variable: BROWSER_STACK_USERNAME + ${username from url above}
- Add Variable: BROWSER_STACK_ACCESS_KEY + ${key from url above}
- Add Variable: BROWSER_STACK_USERNAME + \${username from url above}
- Add Variable: BROWSER_STACK_ACCESS_KEY + \${key from url above}

View File

@@ -1,10 +1,13 @@
# Building
## Browser standards
We strongly believe that staying close to browser standards will be the best long term investment for your code. It is the basis for all our recommendations, and it means that sometimes we will not recommend a popular feature or functionality. It also means we can be faster to adopt and recommend new browser standards.
## Building web apps
Building is a necessary optimization when shipping apps to production. Generally speaking, build tools accomplish some or all of the following:
1. Reduce app size (tree shaking, inlining, minification etc.)
2. Bundling and code splitting (combining many into few files)
3. Transforming/polyfilling standard code for older browsers
@@ -14,8 +17,10 @@ Building is a necessary optimization when shipping apps to production. Generally
Our recommended setups address the first four points but refrain from introducing non-standard features. We think it's best to avoid those, as they might lock your source code to a specific build setup which can be hard to get away from at a later time. Javascript is evolving fast, your code can quickly become out of sync with new developments.
## Using `index.html` as an entry point
Our configs for `rollup` & `webpack` are unique in that sense that they take a single html file as an entry point.
Doing so allows you to work with the same entry point no matter if you use
- webpack
- rollup
- es-dev-server
@@ -27,6 +32,7 @@ This allows you to easily switch between build configurations; if you want to sw
It also means you can use `es-dev-server` for your regular development, and then use either `rollup` or `webpack` to prepare your application for your production environment.
## Rollup
We recommend [Rollup](https://rollupjs.org/) for building front-end projects. Rollup is convenient to use and gets out of your way. It is easy to understand what's going on. Quite a relief in a world of complex javascript tooling.
Rollup is focused on statically analyzing es module based projects, significantly reducing the size of your app through tree shaking, minification and code splitting. Rollup can output es modules, making use of the native module loader available in modern browsers.
@@ -34,6 +40,7 @@ Rollup is focused on statically analyzing es module based projects, significantl
Our [default configuration](/building/building-rollup.html) gets your started with a setup for modern browsers, and optionally for supporting legacy browsers.
## Webpack
[Webpack](https://webpack.js.org/) is a popular and flexible build tool, with a large ecosystem of plugins. Out of the box, webpack handles different module formats, such as esm, commonjs, amd and umd. It is not able to output native es modules, relying instead on it's own module loader.
Compared to rollup it is a more complex tool, with more options for composing and managing complex projects. It also comes with a dev server with features such as auto-reload and hot module reloading.

View File

@@ -1,3 +1,3 @@
# Codelabs
TODO
TODO

View File

@@ -1,6 +1,7 @@
# Developing
## Going buildless
Browsers have improved a lot over the past years. It's now possible to do web development without requiring any build tools, using the native module loader of the browser. We think this is a great fit for web components, and we recommend this as a general starting point.
Build tools can quickly add a lot of complexity to your code, and make your code reliant on a specific build setup. We think it's best to avoid them during development, or only add them for light transformations if you know what you're doing.
@@ -8,9 +9,11 @@ Build tools can quickly add a lot of complexity to your code, and make your code
Read [this article](https://dev.to/open-wc/developing-without-a-build-1-introduction-26ao) to learn more about this approach.
## Development server
We created [es-dev-server](https://open-wc.org/developing/es-dev-server.html) to help developing without build tools.
## Web component libraries
You can write web components using just the basic web component APIs. This can be a great choice when you're looking to keep dependencies low. But generally, we recommend using lightweight libraries to help improve the developer experience and reduce boilerplate.
We recommend [lit-html](https://www.npmjs.com/package/lit-html) with the [lit-element](https://www.npmjs.com/package/lit-element) base class as a general-purpose library for building web components. `lit-html` is feature complete, extremely lightweight and offers a great development experience. Check out the [lit-html page](/developing/lit-html/) for code examples and more information.
@@ -18,6 +21,7 @@ We recommend [lit-html](https://www.npmjs.com/package/lit-html) with the [lit-el
In the code snippets throughout our documentation we use `lit-html` and `lit-element`, but our recommendations and tools are not specific to them. You should be able to use them with any web component library that follows browser standards. If you do run into issues, or have any questions, let us know about it!
### Alternative libraries
Besides `lit-html`, there are other great options available:
- [haunted](https://www.npmjs.com/package/haunted) functional-style web components, with react-like hooks
@@ -27,13 +31,17 @@ Besides `lit-html`, there are other great options available:
- [stencil](https://stenciljs.com/) web component with typescript and JSX (requires a build step)
## Code examples
Check out the [code examples](/developing/code-examples/) page for a collection of best practices and design patterns.
## Testing
Check out our [testing documentation](/testing/) for help with setting up testing.
## Building
When you are ready to ship your app to production, or when you need to test your app on older browsers, take a look at our [building documentation](/building/) to get you started.
## Further reading
See: [awesome lit-html](https://github.com/web-padawan/awesome-lit-html) for a great collection of resources.

View File

@@ -16,4 +16,4 @@ We're actively looking to extend this page with common best practices. If you ha
Every developer at some point will run into the problem of moving some data upwards to a parent element. While there are many ways to manage state in your application like Redux, or passing down a bound function to a child element to mutate state in the parent, our default recommendation for moving data upwards is simply using events. The benefits of using events are that it's close to the platform, and will always have the same expected behavior across frameworks. You can find a demo of using `CustomEvents` [here](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F12-firing-events.js).
If you find yourself moving a lot of data around, it may be time to look into some state management libraries like [Redux](https://redux.js.org/) or consider some more advanced composition techniques with [slotting](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F09-slotting.js).
If you find yourself moving a lot of data around, it may be time to look into some state management libraries like [Redux](https://redux.js.org/) or consider some more advanced composition techniques with [slotting](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F09-slotting.js).

View File

@@ -2,45 +2,49 @@
## lit-html and lit-element
A simple base class for creating fast, lightweight web components.
A simple base class for creating fast, lightweight web components.
[LitElement documentation](https://lit-element.polymer-project.org)
[lit-html documentation](https://lit-html.polymer-project.org)
Click on the links below to view live code samples:
* [Basic](https://open-wc-lit-demos.stackblitz.io/basic)
- [01 Basic setup](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F01-basic-setup.js)
- [02 Manage properties](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F02-manage-properties.js)
- [03 Property changes](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F03-property-changes.js)
- [04 Properties and attributes](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F04-properties-and-attributes.js)
- [05 Passing properties](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F05-passing-properties.js)
- [06 Handle events](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F06-handle-events.js)
- [07 Conditional rendering](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F07-conditional-rendering.js)
- [08 Repeated templates](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F08-repeated-templates.js)
- [09 Update arrays and objects](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F09-update-arrays-and-objects.js)
- [10 Render styles](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F10-render-styles.js)
- [11 Fetching data](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F11-fetching-data.js)
- [12 Firing events](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F12-firing-events.js)
* [Intermediate](https://open-wc-lit-demos.stackblitz.io/intermediate)
- [01 First updated](https://stackblitz.com/edit/open-wc-lit-demos?file=01-intermediate%2F01-first-updated.js)
- [02 Updated](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F02-updated.js)
- [03 Lifecycle](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F03-lifecycle.js)
- [04 Computed properties](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F04-computed-properties.js)
- [05 Querying dom](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F05-querying-dom.js)
- [06 Light dom](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F06-light-dom.js)
- [07 Reflecting attributes](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F07-reflecting-attributes.js)
- [08 Dynamic repeated templates](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F08-dynamic-repeated-templates.js)
- [09 Slotting](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F09-slotting.js)
* [Advanced](https://open-wc-lit-demos.stackblitz.io/advanced)
- [01 Property setter observer](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F01-property-setter-observer.js)
- [02 Until directive](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F02-until-directive.js)
- [03 Template wrapping](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F03-template-wrapping.js)
- [04 Shared templates](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F04-shared-templates.js)
- [05 Shared styles](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F05-shared-styles.js)
- [06 External template](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F06-external-template.js)
- [07 Template factories](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F07-template-factories.js)
- [08 Should update](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F08-should-update.js)
- [Basic](https://open-wc-lit-demos.stackblitz.io/basic)
- [01 Basic setup](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F01-basic-setup.js)
- [02 Manage properties](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F02-manage-properties.js)
- [03 Property changes](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F03-property-changes.js)
- [04 Properties and attributes](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F04-properties-and-attributes.js)
- [05 Passing properties](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F05-passing-properties.js)
- [06 Handle events](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F06-handle-events.js)
- [07 Conditional rendering](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F07-conditional-rendering.js)
- [08 Repeated templates](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F08-repeated-templates.js)
- [09 Update arrays and objects](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F09-update-arrays-and-objects.js)
- [10 Render styles](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F10-render-styles.js)
- [11 Fetching data](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F11-fetching-data.js)
- [12 Firing events](https://stackblitz.com/edit/open-wc-lit-demos?file=01-basic%2F12-firing-events.js)
- [Intermediate](https://open-wc-lit-demos.stackblitz.io/intermediate)
- [01 First updated](https://stackblitz.com/edit/open-wc-lit-demos?file=01-intermediate%2F01-first-updated.js)
- [02 Updated](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F02-updated.js)
- [03 Lifecycle](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F03-lifecycle.js)
- [04 Computed properties](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F04-computed-properties.js)
- [05 Querying dom](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F05-querying-dom.js)
- [06 Light dom](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F06-light-dom.js)
- [07 Reflecting attributes](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F07-reflecting-attributes.js)
- [08 Dynamic repeated templates](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F08-dynamic-repeated-templates.js)
- [09 Slotting](https://stackblitz.com/edit/open-wc-lit-demos?file=02-intermediate%2F09-slotting.js)
- [Advanced](https://open-wc-lit-demos.stackblitz.io/advanced)
- [01 Property setter observer](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F01-property-setter-observer.js)
- [02 Until directive](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F02-until-directive.js)
- [03 Template wrapping](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F03-template-wrapping.js)
- [04 Shared templates](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F04-shared-templates.js)
- [05 Shared styles](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F05-shared-styles.js)
- [06 External template](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F06-external-template.js)
- [07 Template factories](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F07-template-factories.js)
- [08 Should update](https://stackblitz.com/edit/open-wc-lit-demos?file=03-advanced%2F08-should-update.js)
## Haunted
@@ -49,25 +53,28 @@ React's Hooks API implemented for web components 👻
Click on the links below to view live code samples:
* [Basic](https://open-wc-haunted-demos.stackblitz.io/basic)
- [01 Basic setup](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F01-basic-setup.js)
- [02 Manage properties](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F02-manage-properties.js)
- [03 Property changes](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F03-property-changes.js)
- [04 Handling attributes](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F04-handling-attributes.js)
- [05 Passing properties](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F05-passing-properties.js)
- [06 Handle events](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F06-handle-events.js)
- [07 Conditional rendering](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F07-conditional-rendering.js)
- [08 Repeated templates](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F08-repeated-templates.js)
- [09 Firing events](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F09-firing-events.js)
- [10 Virtual Components](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F10-virtual-components.js)
- [11 Using styles](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F11-using-styles.js)
* [Intermediate](https://open-wc-haunted-demos.stackblitz.io/intermediate)
- [01 Using state](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F01-using-state.js)
- [02 Using effects](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F02-using-effects.js)
- [03 Fetch data](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F03-fetch-data.js)
- [04 Using reducer](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F04-using-reducer.js)
- [05 Using ref](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F04-using-ref.js)
- [06 Using memo](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F06-using-memo.js)
* [Advanced](https://open-wc-haunted-demos.stackblitz.io/advanced)
- [01 Using context](https://stackblitz.com/edit/open-wc-haunted-demos?file=03-advanced%2F01-using-context.js)
- [Basic](https://open-wc-haunted-demos.stackblitz.io/basic)
- [01 Basic setup](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F01-basic-setup.js)
- [02 Manage properties](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F02-manage-properties.js)
- [03 Property changes](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F03-property-changes.js)
- [04 Handling attributes](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F04-handling-attributes.js)
- [05 Passing properties](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F05-passing-properties.js)
- [06 Handle events](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F06-handle-events.js)
- [07 Conditional rendering](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F07-conditional-rendering.js)
- [08 Repeated templates](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F08-repeated-templates.js)
- [09 Firing events](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F09-firing-events.js)
- [10 Virtual Components](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F10-virtual-components.js)
- [11 Using styles](https://stackblitz.com/edit/open-wc-haunted-demos?file=01-basic%2F11-using-styles.js)
- [Intermediate](https://open-wc-haunted-demos.stackblitz.io/intermediate)
- [01 Using state](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F01-using-state.js)
- [02 Using effects](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F02-using-effects.js)
- [03 Fetch data](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F03-fetch-data.js)
- [04 Using reducer](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F04-using-reducer.js)
- [05 Using ref](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F04-using-ref.js)
- [06 Using memo](https://stackblitz.com/edit/open-wc-haunted-demos?file=02-intermediate%2F06-using-memo.js)
- [Advanced](https://open-wc-haunted-demos.stackblitz.io/advanced)
- [01 Using context](https://stackblitz.com/edit/open-wc-haunted-demos?file=03-advanced%2F01-using-context.js)

View File

@@ -5,10 +5,13 @@ We recommend [lit-html](https://www.npmjs.com/package/lit-html) with the [lit-el
Under the hood new Web Component APIs such as [Constructable Stylesheets](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) are used when they are available. As browser support improves, you get performance improvements for free.
## Getting started
To get started, we recommend using our project scaffolding:
```bash
npm init @open-wc
```
## Examples
Check out the [code examples](/developing/code-examples/) page for a collection of best practices and design patterns.
Check out the [code examples](/developing/code-examples/) page for a collection of best practices and design patterns.

View File

@@ -10,5 +10,5 @@ In alphabetical order:
- [lit-router](https://github.com/danevans/lit-router)
- [pwa-helpers router](https://github.com/Polymer/pwa-helpers#routerjs)
- [redux first routing](https://github.com/mksarge/redux-first-routing)
- [simplr-router](https://github.com/Matsuuu/simplr-router)
- [simplr-router](https://github.com/Matsuuu/simplr-router)
- [vaadin-router](https://github.com/vaadin/vaadin-router)

View File

@@ -7,6 +7,7 @@
Types provide valuable information about the nature of code, and help identify typos, enable refactoring, etc. Most editors these days provide some kind of IntelliSense based on type information gleaned from the code. My favorite is Visual Studio Code. With proper type information it can give you symbol defintions on hover, code completion, symbol renaming across files, etc.
### Benefits of Types
1. Early detection of type errors
2. Better code analysis
3. Improved IDE support
@@ -50,13 +51,8 @@ In order to get type linting in a JavaScript project using VS Code all you need
"alwaysStrict": true,
"esModuleInterop": true
},
"include": [
"**/*.js",
"node_modules/@open-wc/**/*.js"
],
"exclude": [
"node_modules/!(@open-wc)"
]
"include": ["**/*.js", "node_modules/@open-wc/**/*.js"],
"exclude": ["node_modules/!(@open-wc)"]
}
```
@@ -65,17 +61,14 @@ In order to get type linting in a JavaScript project using VS Code all you need
If you wish to use our typings in TypeScript you will to do a little more.
You will need to add to this to your `tsconfig.json`.
```json
{
"compilerOptions": {
"allowJs": true
},
"include": [
"node_modules/@open-wc/**/*.js"
],
"exclude": [
"node_modules/!(@open-wc)"
]
"include": ["node_modules/@open-wc/**/*.js"],
"exclude": ["node_modules/!(@open-wc)"]
}
```
@@ -83,7 +76,6 @@ e.g. we need to include the js files from @open-wc and you can not have it in an
However as `allowJs` prevents you from generating definition files for your own typescript files ([issue 7546](https://github.com/Microsoft/TypeScript/issues/7546)) you probably want to have an alternative config `tsconfig.build.json` for that.
```json
{
"extends": "./tsconfig.json",
@@ -95,6 +87,7 @@ However as `allowJs` prevents you from generating definition files for your own
```
You can then use it like so in you `package.json`
```json
{
"scripts": {
@@ -105,11 +98,12 @@ You can then use it like so in you `package.json`
```
That way
- `tsconfig.json` will be used by the language server (in VS code)
- `tsconfig.build.json` will be used to build your typescript project (including definition files)
Example how a full config might look like
```json
{
"compilerOptions": {
@@ -125,12 +119,7 @@ Example how a full config might look like
"alwaysStrict": true,
"esModuleInterop": true
},
"include": [
"**/*.js",
"node_modules/@open-wc/**/*.js"
],
"exclude": [
"node_modules/!(@open-wc)"
]
"include": ["**/*.js", "node_modules/@open-wc/**/*.js"],
"exclude": ["node_modules/!(@open-wc)"]
}
```

View File

@@ -6,20 +6,20 @@ In this section you can find answers to frequently asked questions regarding jav
[[toc]]
**Deep dives:**
- [Component Libraries](./component-libraries.html)
- [Rerender not triggered](./rerender.html)
- [Unit testing custom events](./unit-testing-custom-events.html)
- [Unit testing initialization error](./unit-testing-init-error.html)
## Custom elements render life cycle
<iframe src="https://andyogo.github.io/custom-element-reactions-diagram/" style="width: 940px; border: none;margin-left: -100px; height: 1350px;"></iframe>
## How can I set `:host` width via a property?
The following example features 3 variations:
- `disabled` style differently if a property is set
- `type` style if type has a certain value
- `width` map a property to a css variable
@@ -71,15 +71,15 @@ Many elements reflect their properties as attributes, and vice versa, like for e
```
```js
console.log(myButton.disabled) // true
console.log(myButton.hasAttribute('disabled')) // true
console.log(myButton.disabled); // true
console.log(myButton.hasAttribute('disabled')); // true
```
If we set the property to false, it'll _reflect_ it to an attribute. (In this case, because it's a boolean attribute, it'll be omitted)
```js
myButton.disabled = false;
console.log(myButton.hasAttribute('disabled')) // false
console.log(myButton.hasAttribute('disabled')); // false
```
This concept is called attribute reflection.
@@ -91,6 +91,7 @@ However, this is not true for the `checked` attribute on an input element of typ
```
It will only set the property the first time:
```js
console.log(mycheck.checked); // true
```

View File

@@ -5,51 +5,67 @@ The hardest part of any project is often getting content onto that first blank p
- [Aybolit](https://web-padawan.github.io/aybolit/)
A growing family of elements with default styling for Bootstrap, Bulma, and Material, as well as a solid white-label basis for extending the underlying functionality with your own custom designs.
- [Bolt](https://boltdesignsystem.com/)
A family of web components built with first-class participation in the Twig templating system for PHP in mind. This set is backed by an expansive catalog of usage variants.
- [Clever Components](https://github.com/CleverCloud/clever-components)
A collection of low-level (atoms) and high-level (domain specific) Web Components made by Clever Cloud for its different Web UIs (public and internal).
- [Elix](https://component.kitchen/elix)
The Elix project aims to create a universal library of all general-purpose user interface patterns commonly found in desktop and mobile UIs, where each pattern is implemented as a well-designed, attractive, high-quality, performant, accessible, localizable, and extensively customizable web component.
- [HelixUI](https://rackerlabs.github.io/helix-ui/)
The HelixUI library provides front-end developers a set of reusable CSS classes and HTML Custom Elements that adhere to Helix design standards, as outlined by Rackspace.
- [Ink Components](https://components.ink/)
Web components for interactive scientific writing, reactive documents and explorable explanations. The Ink Components library can bring your math and science documents to the next level by breathing life into charts, equations, and variables that can be used throughout your application or content.
- [Io GUI](https://io-gui.dev/#page=elements)
Io is a UI framework for web applications and custom elements. It supports virtual DOM, reactive rendering and data binding. It includes a design system composed of UI elements ranging from simple input fields, to menu systems and responsive layouts. Its unique feature is the ability to create visually complex, yet fast and GPU-optimized elements using WebGL shaders.
- [Ionic UI Components](https://ionicframework.com/docs/components)
Take advantage of the component system that powers Ionic applications with a large ecosystem to choose from and in-depth usage instructions, no matter the framework you use.
- [Lightning Web Components by SalesForce](https://developer.salesforce.com/docs/component-library/overview/components)
Lightning Web Components are now the go-to standard for developing applications in the SalesForce ecosystem, and with the power of web components, they can be the basis of applications outside of their ecosystem, too!
- [Lion Web Components by ING Bank](https://github.com/ing-bank/lion)
Lion web components is a set of highly performant, accessible and flexible Web Components. They provide an unopinionated, white label layer that can be extended to your own layer of components.
- [Material Web Components](https://material-components.github.io/material-components-web-components/demos/index.html)
Material Design Components from Material Design team themselves. Stay as close as possible to the changing specification with these components from Google's own Material Design team.
- [Morningstar](http://designsystem.morningstar.com/components/component-status.html)
The Morningstar Design System combines vanilla HTML/CSS with web components in just the right proportions to empower the design and development of wide reaching content and functionality.
- [UI5 Web Components](https://sap.github.io/ui5-webcomponents/)
Get the power and flexibility of SAP's UI5 rendering stack with the ergonomics and ease of use of web components, and bring enterprise-grade features, Fiori UX and themeability home to your application.
- [Smart HTML Elements](https://www.htmlelements.com)
With the goal of helping to deliver modern responsive websites and applications that work on any device and are pleasure to use, the Smart HTML Elements collection is one the most feature rich and comprehensive javascript user interface frameworks.
- [Vaadin](https://vaadin.com/components)
Vaadin has a comprehensive set of beautifully crafted, performant, and adaptable UI components for modern mobile-first Web apps. They are the ideal building blocks for Progressive Web Applications.
- [Weightless](https://weightless.dev/)
A lightweight component library featuring a wide array of design concepts. It surfaces a good amount of customizability via comprehensive component and CSS Custom Property APIs with a small footprint, [just short of 30KB](https://bundlephobia.com/result?p=weightless@0.0.34).
- [Wired Elements](https://wiredjs.com/)
A set of common UI elements with a hand-drawn, sketchy look. These can be used for wireframes, mockups, or just the fun hand-drawn look.

View File

@@ -3,18 +3,22 @@
# Modifying an array or objects members does not trigger rerender
Imagine the following scenario: you've created a custom element that observes an `items` property:
```js
class MyEl extends LitElement {
render() {/*...*/}
render() {
/*...*/
}
static get properties() {
return {
items: { type: Array }
}
items: { type: Array },
};
}
}
```
You might think that changing *one of* the items should trigger a rerender:
You might think that changing _one of_ the items should trigger a rerender:
```js
const myEl = document.querySelector('my-el');
myEl.items; // [{ name: 'foo' }, { name: 'bar' }]
@@ -24,16 +28,19 @@ myEl.items[0].name = 'baz';
But this won't cause the element to update. Why not?
### Reference Values
Javascript has two kinds of types: direct values and reference values. Direct values are things like `'a string'` or `1` or `true`. Their value flows directly from what they are, and there's no ambiguity - the number 1 is always and simply the number 1.
Reference values like `Object` and `Array` are like containers for multiple direct (or reference) values. An array for instance can contain multiple values at any numeric index.
In the case of direct values, equality is determined by directly comparing the value:
In the case of direct values, equality is determined by directly comparing the value:
```js
1 === 1 // true
'three' === 'three' // true
1 === 1; // true
'three' === 'three'; // true
```
But in the case of reference types, the thing that is compared is the *reference* to the object, not its contents.
But in the case of reference types, the thing that is compared is the _reference_ to the object, not its contents.
```js
const o = { foo: 'bar' }
const p === { foo: 'bar' }
@@ -41,19 +48,17 @@ o === p // false
```
### LitElement's Property System
LitElement's property system only observes changes to the reference. Recursively listening for changes to child properties would be prohibitively expensive, especially for large nested objects.
Therefore, setting a child or grandchild property of `myEl.items` will *not* trigger a render.
Therefore, setting a child or grandchild property of `myEl.items` will _not_ trigger a render.
So what can we do if we need to update a nested child? Immutable data patterns can help us.
```js
const [oldItem, ...rest] = myEl.items;
const newItem = { name: 'baz' };
myEl.items = [
newItem,
...rest,
];
myEl.items = [newItem, ...rest];
```
For objects, the syntax is even simpler:
@@ -62,15 +67,16 @@ For objects, the syntax is even simpler:
// example of updating the `changed` property on `myEl.objectProperty`
myEl.objectProperty = {
...myEl.objectProperty,
changed: newVal
changed: newVal,
};
```
### Summary
Polymer slack user Dracco adds:
> Actually it's not about JS, every objective language can have a collection structure, but modifying the collection does not modify the object.
> Comparing in JS means comparing references (it would be impossible to make a universal and fast content comparison), so pushing things to an array keeps the reference the same (as it is still the same instance of an Array class) - just the contents change.
> Similarly in `class Person { constructor() { this.isBanned = false; } }`, if you create a new instance (`const p = new Person();`) and then modify the property (`p.isBanned = true;`), it is still the same instance it was before, just the property differs.
> Comparing in JS means comparing references (it would be impossible to make a universal and fast content comparison), so pushing things to an array keeps the reference the same (as it is still the same instance of an Array class) - just the contents change.
> Similarly in `class Person { constructor() { this.isBanned = false; } }`, if you create a new instance (`const p = new Person();`) and then modify the property (`p.isBanned = true;`), it is still the same instance it was before, just the property differs.
-- <cite>Dracco</cite>

View File

@@ -1,18 +1,20 @@
# Testing Event Listeners in lifecycle events
Let's say you have a mixin that dispatches an event on `firstUpdated` and `connectedCallback`:
```js
const mixin = superclass => class extends superclass {
firstUpdated() {
super.firstUpdated();
this.dispatchEvent(new CustomEvent('first-updated'));
}
connectedCallback() {
super.connectedCallback();
this.dispatchEvent(new CustomEvent('connected-callback'));
}
};
```js
const mixin = superclass =>
class extends superclass {
firstUpdated() {
super.firstUpdated();
this.dispatchEvent(new CustomEvent('first-updated'));
}
connectedCallback() {
super.connectedCallback();
this.dispatchEvent(new CustomEvent('connected-callback'));
}
};
```
These are the suggested ways of testing these events:
@@ -32,7 +34,6 @@ it('dispatches a custom event on firstUpdated', async () => {
});
```
#### connectedCallback
For `connectedCallback`, since this callback is fired immediately after calling `fixture`, you can't catch it anymore. What you can do is define a new component and test its callback function in a `setTimeout`.

View File

@@ -27,11 +27,9 @@ This method should be called before the first render when the element gets attac
## The test case
```js
it("should throw when missing definition property", async () => {
it('should throw when missing definition property', async () => {
const el = new StringField();
expect(() => el.checkProperties()).to.throw(
'property "definition" required'
);
expect(() => el.checkProperties()).to.throw('property "definition" required');
});
```
@@ -45,7 +43,7 @@ it('checkProperties gets called', async () => {
checkProperties() {
checkCalled = true;
}
}
},
);
await fixture(`<${tag}></${tag}>`);
expect(checkCalled).to.be.true;

View File

@@ -13,6 +13,7 @@ npm init @open-wc
```
## Available Recommendations
- [Developing](/developing/)
- [Linting](/linting/)
- [Testing](/testing/)
@@ -26,8 +27,10 @@ npm init @open-wc
You can read all about our motivation and our philosophy [here](/about/).
## FAQ
- [FAQ](/faq/)
## Example
The [Set-Game Example](https://github.com/open-wc/example-vanilla-set-game/) uses all the above recommendations.
You can find a published storybook here: [https://example-set-game-open-wc.netlify.com/](https://example-set-game-open-wc.netlify.com/).

View File

@@ -3,12 +3,14 @@
Linting can help you write consistent code, and easily prevent mistakes. Open-wc recommends the following tools:
We recommend
- [ESLint](https://eslint.org/) to lint your es6 code
- [Prettier](https://prettier.io/) to auto format your code
- [lint-staged](https://www.npmjs.com/package/lint-staged) to apply linting fixed only to changed files
- [commitlint](https://www.npmjs.com/package/@commitlint/cli) so commit messages follow a certain flow
## Setup
```bash
npm init @open-wc
# Upgrade > Linting
@@ -19,6 +21,7 @@ This is part of the default [open-wc](https://open-wc.org/) recommendation
:::
### Manual
- `yarn add --dev @open-wc/eslint-config @open-wc/prettier-config lint-staged husky @commitlint/cli @commitlint/config-conventional`
- Copy [.eslintignore](https://github.com/open-wc/open-wc/blob/master/packages/create/src/generators/linting-eslint/templates/static/.eslintignore) to `.eslintignore`
- Copy [.eslintrc.js](https://github.com/open-wc/open-wc/blob/master/packages/create/src/generators/linting-prettier/templates/static/.eslintrc.js) to `.eslintrc.js`
@@ -54,6 +57,7 @@ This is part of the default [open-wc](https://open-wc.org/) recommendation
## Usage
Run:
- `npm run lint` to check if any file is correctly formatted
- `npm run format` to auto format your files

View File

@@ -3,6 +3,7 @@
Use [TypeScript](https://www.typescriptlang.org/) to type lint your es6 JSDoc annotated code.
## Setup
```bash
npm init @open-wc linting-types-js
```
@@ -12,6 +13,7 @@ This is an OPTIONAL recommendation. You will need to opt-in by running the gener
:::
## Manual
- `yarn add --dev typescript`
- Copy [tsconfig.json](https://github.com/open-wc/open-wc/blob/master/packages/create/src/generators/linting-types-js/templates/static/tsconfig.json) to `tsconfig.json`
- Add these scripts to your package.json
@@ -32,6 +34,7 @@ For general information about types please see [developing/types](../developing/
## Usage
Run:
- `npm run lint:types` to check if you have type errors
## Type linting error example

View File

@@ -12,12 +12,14 @@ To publish your Web Component we recommend [netlify](https://www.netlify.com/).
Head over to [netlify](https://www.netlify.com/) and register.
Select your github account and repository.
If you follow these recommendations all you need to do is
- Build command: `npm run site:build`
- Publish directory: `_site`
And you're all set up.
## Example
The [Set-Game Example](https://github.com/open-wc/example-vanilla-set-game/) has the default publishing via storybook on netlify.
You can see the finished page here: [https://example-set-game-open-wc.netlify.com/](https://example-set-game-open-wc.netlify.com/).
@@ -28,6 +30,7 @@ If you're using our [build configuration](http://open-wc.org/building), the `dis
- Build command: `npm run build`
- Copy the `dist` directory to your desired location: `sudo cp -R dist /Library/WebServer/Documents/myapp`
- Add a `<VirtualHost>` directive to `httpd.conf`, either directly or by an `Include` directive:
```
<VirtualHost *:80>
DocumentRoot "/Library/WebServer/Documents/myapp"
@@ -40,6 +43,7 @@ If you're using our [build configuration](http://open-wc.org/building), the `dis
</Directory>
</VirtualHost>
```
- Restart Apache: `sudo /usr/sbin/apachectl restart`
- Open the page in your browser using the URL `http://mypwa.localhost/`

View File

@@ -1,6 +1,6 @@
# Testing
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
Testing is an important part of any software project. We have collected a set of libraries, tools and best practices to get you started with testing.

View File

@@ -439,8 +439,7 @@ Alternatively, you can create a `workbox-config.js` in the root of your project,
```js
const { createDefaultConfig } = require('@open-wc/building-rollup');
const deepmerge = require('deepmerge');
const { injectManifest, /* generateSW */ } = require('rollup-plugin-workbox');
const { injectManifest /* generateSW */ } = require('rollup-plugin-workbox');
const basicConfig = createDefaultConfig({
input: './index.html',
@@ -452,9 +451,7 @@ const basicConfig = createDefaultConfig({
const workboxConfig = require('./workbox-config.js');
export default merge(basicConfig, {
plugins: [
injectManifest(workboxConfig),
],
plugins: [injectManifest(workboxConfig)],
});
```

View File

@@ -1,6 +1,6 @@
# Building utils
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
Utils for `@open-wc` building packages.

View File

@@ -1,8 +1,9 @@
# Webpack
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
## Configuration
Webpack configuration to help you get started building modern web applications. You write modern javascript using the latest browser features, webpack will optimize your code for production ensure it runs on all supported browsers.
The input for webpack is the same `index.html` you use for development. Any module scripts in your index are run through webpack and your index is updated with the output from rollup.
@@ -12,11 +13,13 @@ See 'config features' for all details. See the extending section for customizati
## Setup
### New project
```bash
npm init @open-wc
```
### Existing project
```bash
npm init @open-wc
# Upgrade > Building > Webpack
@@ -25,6 +28,7 @@ npm init @open-wc
### Manual setup
1. Install the required dependencies:
```bash
npm i -D @open-wc/building-webpack webpack webpack-cli es-dev-server
```
@@ -47,8 +51,9 @@ module.exports = createDefaultConfig({
```
3. Create an `index.html`:
```html
<!doctype html>
<!DOCTYPE html>
<html>
<head></head>
<body>
@@ -62,35 +67,42 @@ module.exports = createDefaultConfig({
We use [webpack-index-html-plugin](https://open-wc.org/building/webpack-index-html-plugin.html). Contrary to other webpack plugins, you **do** need to include your app's module entrypoint in your `index.html`. This allows you to use the same index during development and when building.
4. Add the following commands to your `package.json`:
```json
{
"scripts": {
"build": "webpack --mode production",
"start:build": "es-dev-server --app-index dist/index.html --open",
"start:build": "es-dev-server --app-index dist/index.html --open"
}
}
```
- `start` runs your app for development, reloading on file changes
- `start:build` runs your app after it has been built using the build command
- `build` builds your app and outputs it in your `dist` directory
## Browser support
`createDefaultConfig` creates a single build of your app for modern browsers (by default last 2 of major browsers). This is recommended if you only need to support modern browsers, otherwise you will need to ship compatibility code for browsers which don't need it.
`createCompatibilityConfig` creates two builds of your app. A modern build like the above, and a legacy build for IE11. Additional code is injected to load polyfills and the correct version of your app. This is recommended if you need to support IE11.
## Config features
All configs:
- resolve bare imports (`import { html } from 'lit-html'`)
- preserve `import.meta.url` value from before bundling
- minify + treeshake js
- minify html and css in template literals
`createDefaultConfig`:
- single build output
- compatible with any browser which supports Web Components
`createCompatibilityConfig`:
- Two build outputs:
- Modern:
- compatible with modern browsers (default: last 2 chrome, firefox safari and edge)
@@ -106,19 +118,19 @@ All configs:
See below for more configuration options.
## Customizing the babel config
You can define your own babel plugins by adding a `.babelrc` or `babel.config.js` to your project. See [babeljs config](https://babeljs.io/docs/en/configuration) for more information.
For example to add support for class properties:
```json
{
"plugins": [
"@babel/plugin-proposal-class-properties"
]
"plugins": ["@babel/plugin-proposal-class-properties"]
}
```
## Adjusting browser support for the modern build
The legacy build targets IE11, which is the earliest browser supported by the webcomponents polyfill. For the modern build we target the lates 2 versions of the major browsers (chrome, firefox, safari and edge).
You can adjust this by adding a [browserslist](https://github.com/browserslist/browserslist) configuration. For example by adding a `.browserslistrc` file to your project, or adding an entry to your package.json. See the [browserslist documentation](https://github.com/browserslist/browserslist) for more information.
@@ -126,7 +138,9 @@ You can adjust this by adding a [browserslist](https://github.com/browserslist/b
> Note: you should not add IE11 or other very early browsers as a target in your browserslist, as it would result in a broken modern build because it makes some assumptions around browser support. Use the `--legacy` flag for legacy builds.
## Extending the webpack config
A webpack config is an object. To extend it, we recommend using `webpack-merge` to ensure plugins are merged correctly. For example to adjust the output folder:
```javascript
const merge = require('webpack-merge');
const { createDefaultConfig } = require('@open-wc/building-webpack');
@@ -137,7 +151,7 @@ const config = createDefaultConfig({
module.exports = merge(config, {
output: {
path: 'build'
path: 'build',
},
});
```
@@ -152,19 +166,23 @@ const configs = createCompatibilityConfig({
input: path.resolve(__dirname, './index.html'),
});
module.exports = configs.map(config => merge(config, {
output: {
path: 'build'
},
}));
module.exports = configs.map(config =>
merge(config, {
output: {
path: 'build',
},
}),
);
```
### Common extensions
::: warning
Some extensions or plugins add non-native or experimental features to your code. This can be bad for the maintenance of your code in the long term, we therefore don't recommend it unless you know what you're doing.
:::
#### Customizing index.html output
If you need to customize the output of your `index.html` you can pass extra options to [webpack-index-html-plugin](https://open-wc.org/building/webpack-index-html-plugin.html):
```javascript
@@ -185,6 +203,7 @@ module.exports = createDefaultConfig({
See the documentation for all options.
#### non index.html entrypoint
By default we look for an `index.html` as entrypoint. If want to use regular entrypoints you will need to provide your `index.html` for output manually:
```javascript
@@ -205,6 +224,7 @@ module.exports = createDefaultConfig({
```
#### Adding or removing polyfills
By default we polyfill `core-js`, `webcomponentsjs` and `fetch`. It is possile to add or remove polyfills by passing `webpack-index-html` configuration like above:
```javascript
@@ -232,6 +252,7 @@ module.exports = createDefaultConfig({
[See the documentation](https://open-wc.org/building/webpack-index-html-plugin.html) for more information.
#### Copy assets
Web apps often include assets such as css files and images. These are not part of your regular dependency graph, so they need to be copied into the build directory.
[copy-webpack-plugin](https://github.com/webpack-contrib/copy-webpack-plugin) is a popular plugin fo this.
@@ -252,11 +273,7 @@ const configs = createCompatibilityConfig({
module.exports = [
// add plugin to the first config
merge(configs[0], {
plugins: [
new CopyWebpackPlugin([
'images/**/*.png',
]),
],
plugins: [new CopyWebpackPlugin(['images/**/*.png'])],
}),
// the second config left untouched
@@ -265,13 +282,14 @@ module.exports = [
```
#### Support typescript
Make sure to prevent any compilation done by the typescript compiler `tsconfig.json`, as babel and webpack do this for you:
```json
{
"compilerOptions": {
"target": "ESNEXT",
"module": "ESNext",
"module": "ESNext"
}
}
```
@@ -279,45 +297,44 @@ Make sure to prevent any compilation done by the typescript compiler `tsconfig.j
Within webpack there are two options to add typescript support.
##### 1. Babel
We recommend using the babel typescript plugin. Add this to your `.babelrc`:
```json
{
"presets": [
"@babel/preset-typescript"
],
"presets": ["@babel/preset-typescript"]
}
```
This the fastest method, as it strips away types during babel transformormation of your code. It will not perform any type checking though. We recommend setting up the type checking as part of your linting setup, so that you don't need to run the typechecker during development for faster builds.
<details>
<summary>Supporting decorators</summary>
::: warning
Please note that decorators will add [non standard syntax](https://open-wc.org/building/building-webpack.html#common-extensions) to your code.
:::
::: warning
Please note that decorators will add [non standard syntax](https://open-wc.org/building/building-webpack.html#common-extensions) to your code.
:::
```json
{
"presets": ["@babel/preset-typescript"],
// for libraries that support babel decorators (lit-element) use:
"plugins": [
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }],
"@babel/plugin-proposal-class-properties"
]
// for libraries that only support typescript:
// "plugins": [
// ["@babel/plugin-proposal-decorators", { "legacy": true }],
// ["@babel/plugin-proposal-class-properties", { "loose": true }]
// ],
}
```
```json
{
"presets": [
"@babel/preset-typescript"
],
// for libraries that support babel decorators (lit-element) use:
"plugins": [
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }],
"@babel/plugin-proposal-class-properties"
]
// for libraries that only support typescript:
// "plugins": [
// ["@babel/plugin-proposal-decorators", { "legacy": true }],
// ["@babel/plugin-proposal-class-properties", { "loose": true }]
// ],
}
```
</details>
##### 2. Plugin
It is also possible to add the webpack typescript plugin, which does typechecking and compiling for you:
```javascript
@@ -342,8 +359,7 @@ module.exports = configs.map(config =>
### Making your app installable
Make sure your PWA meets the installable criteria, which you can find [here](https://developers.google.com/web/fundamentals/app-install-banners/). You can find a tool to generate your `manifest.json` [here](https://www.pwabuilder.com/generate). When your app has a service worker with a `fetch` handler (generated by this configuration), a `manifest.json`, and is served over HTTPS, your app is ready to be installed.
Make sure your PWA meets the installable criteria, which you can find [here](https://developers.google.com/web/fundamentals/app-install-banners/). You can find a tool to generate your `manifest.json` [here](https://www.pwabuilder.com/generate). When your app has a service worker with a `fetch` handler (generated by this configuration), a `manifest.json`, and is served over HTTPS, your app is ready to be installed.
### Enabling the service worker
@@ -358,9 +374,10 @@ This configuration will by default generate a service worker for you, using [wor
}
</script>
```
### Overriding the workbox config
If you want to override the default config with your own workbox configuration, you can disable the default workbox configuration by setting `options.plugins.workbox` to false in the `options` object that you pass to `createBasicConfig`, and then you can override the plugins
If you want to override the default config with your own workbox configuration, you can disable the default workbox configuration by setting `options.plugins.workbox` to false in the `options` object that you pass to `createBasicConfig`, and then you can override the plugins
```js
const merge = require('deepmerge');
@@ -370,13 +387,12 @@ const createDefaultConfig = require('@open-wc/building-webpack');
const defaultConfig = createDefaultConfig({
plugins: {
workbox: false,
}
},
});
module.exports = merge(defaultConfig, {
plugins: [new InjectManifest(/* */)],
});
```
You can find the options for configuring Workbox [here](https://developers.google.com/web/tools/workbox/modules/workbox-build).
@@ -387,9 +403,9 @@ To opt out of using workbox to generate a service worker, you can disabled it by
```js
module.exports = createBasicConfig({
plugins: {
workbox: false
}
plugins: {
workbox: false,
},
});
```
@@ -397,7 +413,7 @@ module.exports = createBasicConfig({
By default, the service worker generated will _not_ call `skipWaiting`. The reason for this is that it becomes very painful very quickly if you're lazyloading code in your application.
If you want to add a user-friendly 'Add To Home Screen' experience, you can use the [pwa-update-available](https://github.com/thepassle/pwa-helpers) web component.
If you want to add a user-friendly 'Add To Home Screen' experience, you can use the [pwa-update-available](https://github.com/thepassle/pwa-helpers) web component.
<script>
export default {

View File

@@ -1,6 +1,6 @@
# Chai A11y aXe
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
This module provides a Chai plugin to perform automated accessibility tests via axe.
@@ -22,27 +22,42 @@ Rules can be ignored by passing `ignoredRules` with a list of ignored rules as a
import { fixture, expect, html } from '@open-wc/testing';
it('passes accessibility test', async () => {
const el = await fixture(html`<button>label</button>`);
const el = await fixture(
html`
<button>label</button>
`,
);
await expect(el).to.be.accessible();
});
it('fails without label', async () => {
const el = await fixture(html`<div aria-labelledby="test-x"></div>`);
const el = await fixture(
html`
<div aria-labelledby="test-x"></div>
`,
);
await expect(el).not.to.be.accessible();
});
it('passes for all rules, ignores attributes test', async () => {
const el = await fixture(html`<div aria-labelledby="test-x"></div>`);
const el = await fixture(
html`
<div aria-labelledby="test-x"></div>
`,
);
await expect(el).to.be.accessible({
ignoredRules: ['aria-valid-attr-value']
ignoredRules: ['aria-valid-attr-value'],
});
});
it('accepts "done" option', (done) => {
fixture(html`<button>some light dom</button>`)
.then((el) => {
it('accepts "done" option', done => {
fixture(
html`
<button>some light dom</button>
`,
).then(el => {
expect(el).to.be.accessible({
done
done,
});
});
});
@@ -56,19 +71,31 @@ The `isAccessible()` and `isNotAccessible()` methods work on Chai's `assert` fun
import { fixture, assert, html } from '@open-wc/testing';
it('passes axe accessible tests', async () => {
const el = await fixture(html`<button>some light dom</button>`);
const el = await fixture(
html`
<button>some light dom</button>
`,
);
await assert.isAccessible(el);
});
it('accepts ignored rules list', async () => {
const el = await fixture(html`<div aria-labelledby="test-x"></div>`);
const el = await fixture(
html`
<div aria-labelledby="test-x"></div>
`,
);
await assert.isAccessible(el, {
ignoredRules: ['aria-valid-attr-value']
ignoredRules: ['aria-valid-attr-value'],
});
});
it('passes for negation', async () => {
const el = await fixture(html`<div aria-labelledby="test-x"></div>`);
const el = await fixture(
html`
<div aria-labelledby="test-x"></div>
`,
);
await assert.isNotAccessible(el);
});
```

View File

@@ -1,6 +1,7 @@
# Open-wc codelabs
## Contributing
Codelabs are written in markdown, h1 (`#`) indicates the codelab title and each h2 (`##`) indicates a codelab step. You can embed links, images and code snippets. See `example-codelabs` for more info.
To display notifications, you can use a aside:
@@ -13,4 +14,4 @@ Possibles classes are: notice, special, warning, callout
You can view the result of a codelab by running the codelab build. This will output the codelab index.html under `/docs/.vuepress/public/codelabs`. You can open it with any browser.
Codelabs are output using the Google Codelab tools. See https://github.com/googlecodelabs/tools for the full documentation.
Codelabs are output using the Google Codelab tools. See https://github.com/googlecodelabs/tools for the full documentation.

View File

@@ -1,14 +1,15 @@
# Codelab A
## Step a
Do this:
```js
class Element extends LitElement {
}
Do this:
```js
class Element extends LitElement {}
```
## Step b
Do that:
![logo](./assets/logo.png)
![logo](./assets/logo.png)

View File

@@ -1,14 +1,15 @@
# Codelab B
## Step a
Do this:
```js
class Element extends LitElement {
}
Do this:
```js
class Element extends LitElement {}
```
## Step b
Do that:
![logo](./assets/logo.png)
![logo](./assets/logo.png)

View File

@@ -1,6 +1,6 @@
# Create Open Web Components
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
## Usage
@@ -13,6 +13,7 @@ npm init @open-wc
:::
This will kickstart a menu guiding you through all available actions.
```
$ npm init @open-wc
npx: installed 14 in 4.074s
@@ -42,6 +43,7 @@ These generators help you kickstart a new app or web component.
They will create a new folder and set up everything you need to get started immediately.
Example usage:
```bash
npm init @open-wc
# Select "Scaffold a new project"
@@ -57,13 +59,13 @@ npm init @open-wc
This generator scaffolds a new starter application. We recommend using this generator at the start of your web component project.
<br/>
## Features
The above generators are the perfect playgrounds to prototype.
Add linting, testing, demoing and building whenever the need arises.
Example usage:
```bash
cd existing-web-component
npm init @open-wc
@@ -73,23 +75,23 @@ npm init @open-wc
### Available Upgrade features
- `Linting`<br>
This generator adds a complete linting setup with ESLint, Prettier, Husky and commitlint.
This generator adds a complete linting setup with ESLint, Prettier, Husky and commitlint.
<br/>
- `Testing`<br>
This generator adds a complete testing setup with Karma, and Karma Browserstack.
This generator adds a complete testing setup with Karma, and Karma Browserstack.
<br/>
- `Demoing`<br>
This generator adds a complete demoing setup with Storybook.
This generator adds a complete demoing setup with Storybook.
<br/>
- `Building > Rollup`<br>
This generator adds a complete building setup with rollup.
This generator adds a complete building setup with rollup.
<br/>
- `Building > Webpack`<br>
This generator adds a complete building setup with webpack.
This generator adds a complete building setup with webpack.
<br/>
<script>

View File

@@ -1,6 +1,6 @@
# Demoing via storybook
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
For demoing and showcasing different states of your Web Component, we recommend using [storybook](https://storybook.js.org/).
@@ -9,24 +9,27 @@ This is part of the default [open-wc](https://open-wc.org/) recommendation
:::
# Features
- Create API documentation/playground
- Show documentation (from markdown) with your element
- Show your source code to copy/paste
- Helper to setup transpilation for dependencies
- Setup that works down to IE11
## Setup
```bash
npm init @open-wc
# Upgrade > Demoing
```
### Manual
- `yarn add @open-wc/demoing-storybook --dev`
- Copy at minimum the [.storybook](https://github.com/daKmoR/create-open-wc/tree/master/src/generators/demoing-storybook/templates/static/.storybook) folder to `.storybook`
- If you want to bring along the examples, you may also copy the `stories` folder.
- Add the following scripts to your package.json
```js
"scripts": {
"storybook": "start-storybook -p 9001",
@@ -48,18 +51,14 @@ npm run storybook
Create an `*.stories.js` (for example `index.stories.js`) file within the `stories` folder.
```js
import {
storiesOf,
html,
} from '@open-wc/demoing-storybook';
import { storiesOf, html } from '@open-wc/demoing-storybook';
storiesOf('Demo|Example Element', module)
.add(
'Alternative Header',
() => html`
<my-el .header=${'Something else'}></my-el>
`,
);
storiesOf('Demo|Example Element', module).add(
'Alternative Header',
() => html`
<my-el .header=${'Something else'}></my-el>
`,
);
```
### Create API documentation/playground
@@ -70,6 +69,7 @@ So this should probably be your default story to gives users documentation, api
For additional edge cases you should add more stories.
Features:
- Show your README.md without leaving storybook
- On the canvas the "knobs" panel is pre selected
- All the knobs are auto generated from your JavaScript Class
@@ -82,22 +82,21 @@ import readme from '../README.md';
storiesOf('Demo|Example Element', module)
.addDecorator(withKnobs)
.add(
'Documentation',
() => withClassPropertiesKnobs(MyEl),
{ notes: { markdown: readme }, options: { selectedPanel: 'storybooks/knobs/panel' } },
)
.add('Documentation', () => withClassPropertiesKnobs(MyEl), {
notes: { markdown: readme },
options: { selectedPanel: 'storybooks/knobs/panel' },
});
```
So with a configuration like this you will get this auto generated.
<img src="https://raw.githubusercontent.com/open-wc/open-wc/master/packages/demoing-storybook/dev_assets/storybook.gif" alt="storybook demo animation" />
For most types this works fine out of the box but if want to provide better knobs you can customize by overriding the
properties definitions and using the [available knobs](https://github.com/storybooks/storybook/tree/5.0.0/addons/knobs#available-knobs).<br>
It creates the knobs by reading `static get properties` (host properties) and `static get _classProperties` (inherited properties).<br>
This is currently pretty specific to LitElement - However there is an attribute/properties documentation spec [in discussion](https://github.com/w3c/webcomponents/issues/776).
```js
import {
withClassPropertiesKnobs,
@@ -127,6 +126,7 @@ By default it will create one simple node from the given Class.
However for a nicer demo it may be needed to set properties or add more lightdom.
You can do so by providing a template. The template must render the custom element
to be tested before other custom elements.
```js
() => withClassPropertiesKnobs(MyEl, {
template: html`
@@ -166,15 +166,19 @@ module.exports = ({ config }) => {
```
### Additional middleware config like a proxy
If you need additional configuration for the storybook dev server you can provide them via a config file `.storybook/middleware.js`.
```js
// example for a proxy middleware to use an api for fetching data to display
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/api/', {
target: 'http://localhost:9010/',
}));
app.use(
proxy('/api/', {
target: 'http://localhost:9010/',
}),
);
};
```

View File

@@ -11,6 +11,7 @@
This example element display some information about...
## Features:
- bigger then you would expect
- still fast
- awesome to learn something
@@ -18,6 +19,7 @@ This example element display some information about...
## How to use
### Installation
```bash
yarn add @foo/my-el
```

View File

@@ -1,10 +1,11 @@
# ES dev server
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
A web server for developing without a build step.
By default, `es-dev-server` acts as a simple static file server. Through flags, different features can be enabled, such as:
- reloading the browser on file changes
- resolve bare module imports using node resolution
- history API fallback for SPA routing
@@ -14,21 +15,27 @@ By default, `es-dev-server` acts as a simple static file server. Through flags,
Compatibility mode enables bundle-free development with modern javascript, es modules and import maps on all major browsers and IE11.
## Getting started
We recommend [following this guide](https://dev.to/open-wc/developing-without-a-build-2-es-dev-server-1cf5) for a step by step overview of different workflows with `es-dev-server`.
## Setup
With our project scaffolding you can set up a pre-configured project:
```bash
npm init @open-wc
```
### Manual
You can also set up the dev server manually:
```bash
npm i -D es-dev-server
```
Add scripts to your `package.json`, modify the flags as needed:
```json
{
"scripts": {
@@ -39,68 +46,77 @@ Add scripts to your `package.json`, modify the flags as needed:
```
Run the server:
```bash
npm run start
```
## Node version
es-dev-server requires node v10 or higher
## Command line flags and Configuration
### Server configuration
| name | type | description |
| -------------------- | -------------- | -------------------------------------------------------------------------- |
| port | number | The port to use, uses a random free port if not set. |
| hostname | string | The hostname to use. Default: localhost |
| open | boolean/string | Opens the browser on app-index, root dir or a custom path |
| app-index | string | The app's index.html file, sets up history API fallback for SPA routing |
| root-dir | string | The root directory to serve files from. Default: working directory |
| base-path | string | Base path the app is served on. Example: /my-app |
| config | string | The file to read configuration from (JS or JSON) |
| help | none | See all options |
| name | type | description |
| --------- | -------------- | ----------------------------------------------------------------------- |
| port | number | The port to use, uses a random free port if not set. |
| hostname | string | The hostname to use. Default: localhost |
| open | boolean/string | Opens the browser on app-index, root dir or a custom path |
| app-index | string | The app's index.html file, sets up history API fallback for SPA routing |
| root-dir | string | The root directory to serve files from. Default: working directory |
| base-path | string | Base path the app is served on. Example: /my-app |
| config | string | The file to read configuration from (JS or JSON) |
| help | none | See all options |
### Development help
| name | type | description |
| -------------------- | -------------- | -------------------------------------------------------------------------- |
| watch | boolean | Reload the browser when files are edited |
| http2 | boolean | Serve files over HTTP2. Sets up HTTPS with self-signed certificates |
| name | type | description |
| ----- | ------- | ------------------------------------------------------------------- |
| watch | boolean | Reload the browser when files are edited |
| http2 | boolean | Serve files over HTTP2. Sets up HTTPS with self-signed certificates |
### Code transformation
| name | type | description |
| -------------------- | -------------- | -------------------------------------------------------------------------- |
| compatibility | string | Compatibility mode for older browsers. Can be: `esm`, `modern` or `all` |
| node-resolve | number | Resolve bare import imports using node resolve |
| preserve-symlinks | boolean | Preserve symlinks when resolving modules. Default false. |
| module-dirs | string/array | Directories to resolve modules from. Used by node-resolve |
| babel | boolean | Transform served code through babel. Requires .babelrc |
| file-extensions | number/array | Extra file extensions to use when transforming code. |
| babel-exclude | number/array | Patterns of files to exclude from babel compilation. |
| babel-modern-exclude | number/array | Patterns of files to exclude from babel compilation on modern browsers. |
| name | type | description |
| -------------------- | ------------ | ----------------------------------------------------------------------- |
| compatibility | string | Compatibility mode for older browsers. Can be: `esm`, `modern` or `all` |
| node-resolve | number | Resolve bare import imports using node resolve |
| preserve-symlinks | boolean | Preserve symlinks when resolving modules. Default false. |
| module-dirs | string/array | Directories to resolve modules from. Used by node-resolve |
| babel | boolean | Transform served code through babel. Requires .babelrc |
| file-extensions | number/array | Extra file extensions to use when transforming code. |
| babel-exclude | number/array | Patterns of files to exclude from babel compilation. |
| babel-modern-exclude | number/array | Patterns of files to exclude from babel compilation on modern browsers. |
Most commands have an alias/shorthand. You can view them by using `--help`.
### Configuration files
We pick up an `es-dev-server.config.js` file automatically if it is present in the current working directory. You can specify a custom config path using the `config` flag.
Configuration options are the same as command line flags, using their camelCased names. Example:
```javascript
module.exports = {
port: 8080,
watch: true,
nodeResolve: true,
appIndex: 'demo/index.html',
moduleDirs: ['node_modules', 'custom-modules']
}
moduleDirs: ['node_modules', 'custom-modules'],
};
```
In addition to the command-line flags, the configuration file accepts these additional options:
| name | type | description |
| -------------------- | -------------- | ------------------------------------------------------------------------ |
| middlewares | array | Koa middlewares to add to the server, read more below. |
| babelConfig | object | Babel config to run with the server |
| name | type | description |
| ----------- | ------ | ------------------------------------------------------ |
| middlewares | array | Koa middlewares to add to the server, read more below. |
| babelConfig | object | Babel config to run with the server |
## Folder structure
`es-dev-server` serves static files using the same structure as your file system. It cannot serve any files outside of the root of the webserver. You need to make sure any files requested, including node modules, are accessible for the webserver.
Click read more to view different strategies for setting up your project's folder structure.
@@ -108,78 +124,81 @@ Click read more to view different strategies for setting up your project's folde
<details>
<summary>Read more</summary>
### index.html in root
### index.html in root
The simplest setup where all files are accessible is to place your index.html at the root of your project:
```
node_modules/...
src/...
index.html
```
The simplest setup where all files are accessible is to place your index.html at the root of your project:
If you run `es-dev-server` regularly from the root of this project, you can access your app at `/` or `/index.html` in the browser.
```
node_modules/...
src/...
index.html
```
### index.html in a subfoolder
If you run `es-dev-server` regularly from the root of this project, you can access your app at `/` or `/index.html` in the browser.
If you move your `index.html` inside a subfolder:
```
node_modules/...
src/...
src/index.html
```
### index.html in a subfoolder
You can access your app in the browser at `/src/` or `/src/index.html`. You can tell `es-dev-server` to explicitly open at this path:
If you move your `index.html` inside a subfolder:
```bash
# with app-index flag
es-dev-server --app-index src/index.html --open
# without app-index flag
es-dev-server --open src/
```
```
node_modules/...
src/...
src/index.html
```
You can also change the root directory of the dev server:
You can access your app in the browser at `/src/` or `/src/index.html`. You can tell `es-dev-server` to explicitly open at this path:
```bash
es-dev-server --root-dir src --open
```
```bash
# with app-index flag
es-dev-server --app-index src/index.html --open
# without app-index flag
es-dev-server --open src/
```
Now your `index.html` is accessible at `/` or `/index.html`. However, the dev server cannot serve any files outside of the root directory. So if your app uses any node modules, they will no longer because accessible.
You can also change the root directory of the dev server:
If you want your index in a subfolder without this being visible in the browser URL, you can set up a file rewrite rule. [Read more here](#rewriting-file-requests)
```bash
es-dev-server --root-dir src --open
```
### Monorepos
Now your `index.html` is accessible at `/` or `/index.html`. However, the dev server cannot serve any files outside of the root directory. So if your app uses any node modules, they will no longer because accessible.
If you are using `es-dev-server` in a monorepo, your node modules are in two different locations. In the package's folder and the repository root:
```
node_modules/...
packages/my-package/node_modules/...
packages/my-package/index.html
```
If you want your index in a subfolder without this being visible in the browser URL, you can set up a file rewrite rule. [Read more here](#rewriting-file-requests)
You will need to make sure the root node_modules folder is accessible to the dev server.
### Monorepos
If your working directory is `packages/my-package` you can use this command:
If you are using `es-dev-server` in a monorepo, your node modules are in two different locations. In the package's folder and the repository root:
```bash
# with app-index
es-dev-server --root-dir ../../ --app-index packages/my-package/index.html --open
# without app-index
es-dev-server --root-dir ../../ --open packages/my-package/index.html
```
```
node_modules/...
packages/my-package/node_modules/...
packages/my-package/index.html
```
If your working directory is the root of the repository you can use this command:
You will need to make sure the root node_modules folder is accessible to the dev server.
```bash
es-dev-server --app-index packages/my-package/index.html --open
```
If your working directory is `packages/my-package` you can use this command:
This is the same approach as serving an index.html in a subdirectory, so the section above applies here as well.
```bash
# with app-index
es-dev-server --root-dir ../../ --app-index packages/my-package/index.html --open
# without app-index
es-dev-server --root-dir ../../ --open packages/my-package/index.html
```
### Base element
If your working directory is the root of the repository you can use this command:
You can set up a `<base href="">` element to modify how files are resolved relatively to your index.html. You can be very useful when your index.html is not at the root of your project.
```bash
es-dev-server --app-index packages/my-package/index.html --open
```
If you use SPA routing, using a base element is highly recommended. [Read more](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
This is the same approach as serving an index.html in a subdirectory, so the section above applies here as well.
### Base element
You can set up a `<base href="">` element to modify how files are resolved relatively to your index.html. You can be very useful when your index.html is not at the root of your project.
If you use SPA routing, using a base element is highly recommended. [Read more](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
</details>
@@ -192,21 +211,23 @@ You can install custom middlewares, using the `middlewares` property.
<details>
<summary>Read more</summary>
The middleware should be a standard koa middleware. [Read more about koa here.](https://koajs.com/)
The middleware should be a standard koa middleware. [Read more about koa here.](https://koajs.com/)
You can use custom middlewares to set up a proxy, for example:
```javascript
const proxy = require('koa-proxies');
You can use custom middlewares to set up a proxy, for example:
```javascript
const proxy = require('koa-proxies');
module.exports = {
port: 9000,
middlewares: [
proxy('/api', {
target: 'http://localhost:9001',
}),
],
};
```
module.exports = {
port: 9000,
middlewares: [
proxy('/api', {
target: 'http://localhost:9001',
})
],
};
```
</details>
### Rewriting file requests
@@ -216,93 +237,96 @@ You can rewrite certain file requests using a simple custom middleware. This can
<details>
<summary>Read more</summary>
Set up a configuration file with a custom middleware:
Set up a configuration file with a custom middleware:
```javascript
module.exports = {
middlewares: [
function rewriteIndex(context, next) {
if (context.url === '/' || context.url === '/index.html') {
context.url = '/src/index.html';
}
return next();
```javascript
module.exports = {
middlewares: [
function rewriteIndex(context, next) {
if (context.url === '/' || context.url === '/index.html') {
context.url = '/src/index.html';
}
],
};
```
This way from the browser you can request `/` or `/index.html` and it will serve `/src/index.html`. This middleware is run before the dev server's file serving logic, which will use the rewritten URL.
return next();
},
],
};
```
This way from the browser you can request `/` or `/index.html` and it will serve `/src/index.html`. This middleware is run before the dev server's file serving logic, which will use the rewritten URL.
</details>
### Typescript support
`es-dev-server` is based around developing without any build tools but you can make it work with typescript as well.
<details>
<summary>Read more</summary>
The easiest way to use the server with typescript is to compile your typescript to javascript before running the server. Just run `tsc` in watch mode and include the compiled js files from your `index.html`.
The easiest way to use the server with typescript is to compile your typescript to javascript before running the server. Just run `tsc` in watch mode and include the compiled js files from your `index.html`.
You can also configure the dev server to consume your typescript files directly. This is done by running the server with a babel plugin to compile your typescript files to javascript.
You can also configure the dev server to consume your typescript files directly. This is done by running the server with a babel plugin to compile your typescript files to javascript.
Note that when compiling typescript with babel it does not do any type checking or special typescript compilation such as decorators, class fields and enums. You can configure babel to cover most of these, but not all. [Read more about babel typescript here](https://babeljs.io/docs/en/babel-plugin-transform-typescript).
Note that when compiling typescript with babel it does not do any type checking or special typescript compilation such as decorators, class fields and enums. You can configure babel to cover most of these, but not all. [Read more about babel typescript here](https://babeljs.io/docs/en/babel-plugin-transform-typescript).
1. Install the preset:
```bash
npm i --save-dev @babel/preset-typescript
```
1. Install the preset:
2. Add a `babel.config.js` or `.babelrc` to your project:
```json
{
"presets": [
"@babel/preset-typescript"
]
}
```
```bash
npm i --save-dev @babel/preset-typescript
```
3. Import a typescript file from your `index.html`
```html
<html>
<head></head>
2. Add a `babel.config.js` or `.babelrc` to your project:
<body>
<script type="module" src="./my-app.ts"></script>
</body>
</html>
```
```json
{
"presets": ["@babel/preset-typescript"]
}
```
4. Run `es-dev-server` with these flags:
```bash
es-dev-server --file-extensions .ts --node-resolve --babel --open
```
3. Import a typescript file from your `index.html`
To add support for experimental features that are normally handled by the typescript compiler, you can add extra babel plugins:
```html
<html>
<head></head>
1. Install the plugins:
```bash
npm i --save-dev @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties
```
<body>
<script type="module" src="./my-app.ts"></script>
</body>
</html>
```
2. Update your babel configuration:
```json
{
"presets": [
"@babel/preset-typescript"
],
// for libraries that support babel decorators (lit-element) use:
"plugins": [
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }],
"@babel/plugin-proposal-class-properties"
]
// for libraries that only support typescript:
// "plugins": [
// ["@babel/plugin-proposal-decorators", { "legacy": true }],
// ["@babel/plugin-proposal-class-properties", { "loose": true }]
// ],
}
```
4. Run `es-dev-server` with these flags:
```bash
es-dev-server --file-extensions .ts --node-resolve --babel --open
```
To add support for experimental features that are normally handled by the typescript compiler, you can add extra babel plugins:
1. Install the plugins:
```bash
npm i --save-dev @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties
```
2. Update your babel configuration:
```json
{
"presets": ["@babel/preset-typescript"],
// for libraries that support babel decorators (lit-element) use:
"plugins": [
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }],
"@babel/plugin-proposal-class-properties"
]
// for libraries that only support typescript:
// "plugins": [
// ["@babel/plugin-proposal-decorators", { "legacy": true }],
// ["@babel/plugin-proposal-class-properties", { "loose": true }]
// ],
}
```
</details>
@@ -314,37 +338,42 @@ Compatibility mode enables bundle-free development with features such as es modu
<summary>Read more</summary>
If you want to make use of import maps, you can provide an import map in your `index.html`. To generate an import map, you can check out our package [import-maps-generate](https://github.com/open-wc/open-wc/tree/master/packages/import-maps-generate), or you can add one manually.
If you want to make use of import maps, you can provide an import map in your `index.html`. To generate an import map, you can check out our package [import-maps-generate](https://github.com/open-wc/open-wc/tree/master/packages/import-maps-generate), or you can add one manually.
Three modes can be enabled:
### esm
`esm` mode adds [es-module-shims](https://github.com/guybedford/es-module-shims) to enable new module features such as dynamic imports and import maps.
Three modes can be enabled:
This mode has a negligible performance impact and is great when working on modern browsers.
### esm
### modern
`modern` mode expands `esm` mode, adding a babel transform and a polyfill loader.
`esm` mode adds [es-module-shims](https://github.com/guybedford/es-module-shims) to enable new module features such as dynamic imports and import maps.
The babel transform uses the [present-env](https://babeljs.io/docs/en/babel-preset-env) plugin. This transforms standard syntax which isn't yet supported by all browsers. By default, it targets the latest two versions of Chrome, Safari, Firefox, and Edge. This can be configured with a [browserslist configuration](https://www.npmjs.com/package/browserslist).
This mode has a negligible performance impact and is great when working on modern browsers.
The polyfill loader does lightweight feature detection to determine which polyfills to load. By default it loads polyfills for web components, these can be turned off or custom polyfills can be added in the configuration.
### modern
This mode has a moderate performance impact. Use this when using new javascript syntax that is not yet supported on all browsers.
`modern` mode expands `esm` mode, adding a babel transform and a polyfill loader.
### all
`all` mode expands `modern` mode by making your code compatible with browsers that don't yet support modules.
The babel transform uses the [present-env](https://babeljs.io/docs/en/babel-preset-env) plugin. This transforms standard syntax which isn't yet supported by all browsers. By default, it targets the latest two versions of Chrome, Safari, Firefox, and Edge. This can be configured with a [browserslist configuration](https://www.npmjs.com/package/browserslist).
In addition to the web component polyfills, it loads the general [core-js polyfills](https://www.npmjs.com/package/core-js) and a polyfill for [fetch](https://www.npmjs.com/package/whatwg-fetch)
The polyfill loader does lightweight feature detection to determine which polyfills to load. By default it loads polyfills for web components, these can be turned off or custom polyfills can be added in the configuration.
When loading your application it detects module support. If it is not supported, your app is loaded through [system-js](https://github.com/systemjs/systemjs) and your code is transformed to `es5`.
This mode has a moderate performance impact. Use this when using new javascript syntax that is not yet supported on all browsers.
The `es5` transformation is only done for browsers which don't support modules, so you can safely use this mode on modern browsers where it acts the same way as `modern` mode.
### all
`all` mode has the same moderate impact as `modern` mode on browsers that support modules. On browsers that don't support modules, it has a heavier impact. Use this mode if you want to verify if your code runs correctly on older browsers without having to run a build.
`all` mode expands `modern` mode by making your code compatible with browsers that don't yet support modules.
In addition to the web component polyfills, it loads the general [core-js polyfills](https://www.npmjs.com/package/core-js) and a polyfill for [fetch](https://www.npmjs.com/package/whatwg-fetch)
When loading your application it detects module support. If it is not supported, your app is loaded through [system-js](https://github.com/systemjs/systemjs) and your code is transformed to `es5`.
The `es5` transformation is only done for browsers which don't support modules, so you can safely use this mode on modern browsers where it acts the same way as `modern` mode.
`all` mode has the same moderate impact as `modern` mode on browsers that support modules. On browsers that don't support modules, it has a heavier impact. Use this mode if you want to verify if your code runs correctly on older browsers without having to run a build.
</details>
## Using es-dev-server programmatically
You can use different components from `es-dev-server` as a library and integrate it with other tools:
<details>
@@ -379,7 +408,7 @@ Returns an array of koa middleware functions.
import Koa from 'koa';
import { createConfig, createMiddlewares } from 'es-dev-server';
const config = createConfig({ });
const config = createConfig({});
const middlewares = createMiddlewares(config);
const app = new Koa();

View File

@@ -1,10 +1,11 @@
# Linting ESLint
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
Use [ESLint](https://eslint.org/) to lint your es6 code.
## Setup
```bash
npm init @open-wc
# Upgrade > Linting
@@ -15,6 +16,7 @@ This is part of the default [open-wc](https://open-wc.org/) recommendation
:::
## Manual
- `yarn add --dev @open-wc/eslint-config`
- Copy [.eslintignore](https://github.com/open-wc/open-wc/blob/master/packages/create/src/generators/linting-eslint/templates/static/.eslintignore) to `.eslintignore`
- Copy [.eslintrc.js](https://github.com/open-wc/open-wc/blob/master/packages/create/src/generators/linting-eslint/templates/static/.eslintrc.js) to `.eslintrc.js`
@@ -29,6 +31,7 @@ This is part of the default [open-wc](https://open-wc.org/) recommendation
## What you get
This will install [`@open-wc/eslint-config`](https://github.com/open-wc/open-wc/blob/master/packages/eslint-config/index.js), a config based on airbnb but allows for some specialities needed for Web Components.
- Apply linting to js and html files
- Apply linting for best practices
- Allow dynamic module imports
@@ -40,6 +43,7 @@ This will install [`@open-wc/eslint-config`](https://github.com/open-wc/open-wc/
## Usage
Run:
- `npm run lint:eslint` to check if any file is not correctly formatted
- `npm run format:eslint` to auto format your files

View File

@@ -1,6 +1,6 @@
# Generate Import Map
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
This will allow you to generate a flat [import-map](https://github.com/WICG/import-maps).
It allows you to fix the "nested" npm problem for front end development.
@@ -14,6 +14,7 @@ This is still in early beta (Windows paths are not supported yet)
:::
## Features
- Generates a flat import-map
- Prompts the user when there are version conflicts that are not automatically resolvable
- Supports resolutions, overrides, and deletions via the `importMap` property in package.json
@@ -46,6 +47,7 @@ npx @import-map/generate
You can add a `importMap` key in your `package.json` file to specify overrides, deletions or resolutions.
`package.json`:
```
{
"name": "my-package",
@@ -64,7 +66,7 @@ You can add a `importMap` key in your `package.json` file to specify overrides,
### Overrides
There may be times where you'll want to override certain imports. For example, if you're using the built-in `std:kv-storage` module along with `kv-storage-polyfill` for nonsupporting browsers, then `kv-storage-polyfill` will be in your lockfile. The generated import map will look like this:
There may be times where you'll want to override certain imports. For example, if you're using the built-in `std:kv-storage` module along with `kv-storage-polyfill` for nonsupporting browsers, then `kv-storage-polyfill` will be in your lockfile. The generated import map will look like this:
```json
{
@@ -87,10 +89,7 @@ You can achieve that via an override in your `package.json`'s `importMap` config
"importMap": {
"overrides": {
"imports": {
"kv-storage-polyfill": [
"std:kv-storage",
"/node_modules/kv-storage-polyfill/index.js"
]
"kv-storage-polyfill": ["std:kv-storage", "/node_modules/kv-storage-polyfill/index.js"]
}
},
"deletions": ["kv-storage-polyfill/"]
@@ -103,18 +102,17 @@ Note that if you apply overrides, you may also need to specify deletions for the
:::
Which will result in the following import map:
```json
{
"imports": {
"std:kv-storage": [
"std:kv-storage",
"/node_modules/kv-storage-polyfill/index.js"
]
"std:kv-storage": ["std:kv-storage", "/node_modules/kv-storage-polyfill/index.js"]
}
}
```
Overrides may be useful for:
- Polyfilling
- Fixing a dependency with a local fork
- Getting a dependency from a CDN instead
@@ -135,12 +133,12 @@ You can also override entire scopes:
}
```
### Deletions
You can apply deletions to the generated import map by adding a `deletions` property to your package.json:
`package.json`:
```json
{
"importMap": {
@@ -159,6 +157,7 @@ There may be times where you have conflicting versions of the same package in yo
Alternatively, you can specify your own resolutions in your package.json.
`package.json`:
```json
{
"importMap": {
@@ -170,11 +169,13 @@ Alternatively, you can specify your own resolutions in your package.json.
```
## Command line flags overview
### Development help
| name | type | description |
| --------------- | -------------- | ------------------------------------------------------------------------ |
| inject-to | string | Injects the import map to the specified html file |
| name | type | description |
| --------- | ------ | ------------------------------------------------- |
| inject-to | string | Injects the import map to the specified html file |
<script>
export default {
mounted() {

View File

@@ -1,6 +1,6 @@
# Resolve import-maps
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
This will allow you to parse and resolve urls by a given [import-map](https://github.com/WICG/import-maps).
@@ -40,16 +40,19 @@ function myResolve(specifier) {
The 3rd parameter of `resolve` is the "baseUrl/basePath" and it's format is `/path/to/root::/subdir/foo`.
You can compare it with an url `http://example.com/subdir/foo`.
- Everything before the `::` is sort of the `domain` e.g. `http://example.com/`
- Everything after is the path/directory to your appliaction
Such a path is needed as import maps support relative pathes as values.
## Acknowledgments
This implementation is heavily based on the [import-maps reference implementation](https://github.com/WICG/import-maps/tree/master/reference-implementation).
Thanks to @domenic and @guybedford for sharing that prototype.
Some adjustments have been made
- Allow to process/resolve node pathes besides urls
- Use mocha/chai for testing (already available in our setup)

View File

@@ -11,17 +11,21 @@ The `karma-esm` plugin fixes this and spins up [es-dev-server](https://open-wc.o
See [the es-dev-server docs](https://open-wc.org/developing/es-dev-server.html) for more details on compatibility with older browsers.
## Usage
We recommend the [testing-karma configuration](https://open-wc.org/testing/testing-karma.html) for a good default karma setup which includes `karma-esm` and many other good defaults.
### Manual setup
To manually set up this plugin, add it as a karma framework:
1. Install the plugin
```bash
npm i -D @open-wc/karma-esm
```
2. Add to your karma config
```javascript
module.exports = {
// define where your test files are, make sure to set type to module
@@ -50,40 +54,47 @@ module.exports = {
```
## Configuration
`karma-esm` can be configured with these options:
| name | type | description |
| ----------------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| nodeResolve | boolean | Transforms bare module imports using node resolve. |
| coverage | boolean | Whether to report test code coverage. |
| importMap | string | Path to import map used for testing. |
| compatibility | string | Compatibility level to run the `es-dev-server` with. |
| coverageExclude | array | Extra glob patterns of tests to exclude from coverage. |
| babelConfig | string | Custom babel configuration file to run on served code. |
| moduleDirs | string | Directories to resolve modules from. Defaults to `node_modules` |
| babel | boolean | Whether to pick up a babel configuration file in your project. |
| fileExtensions | array | Custom file extensions to serve as es modules. |
| polyfills | object | Polyfill configuration. |
| devServerPort | number | port of server that serves the modules. Note that this is not the karma port. Picks a random port if not set. |
| name | type | description |
| --------------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| nodeResolve | boolean | Transforms bare module imports using node resolve. |
| coverage | boolean | Whether to report test code coverage. |
| importMap | string | Path to import map used for testing. |
| compatibility | string | Compatibility level to run the `es-dev-server` with. |
| coverageExclude | array | Extra glob patterns of tests to exclude from coverage. |
| babelConfig | string | Custom babel configuration file to run on served code. |
| moduleDirs | string | Directories to resolve modules from. Defaults to `node_modules` |
| babel | boolean | Whether to pick up a babel configuration file in your project. |
| fileExtensions | array | Custom file extensions to serve as es modules. |
| polyfills | object | Polyfill configuration. |
| devServerPort | number | port of server that serves the modules. Note that this is not the karma port. Picks a random port if not set. |
### nodeResolve
Node resolve is necessary when you have 'bare imports' in your code and are not using import maps to resolve them.
It transforms: `import foo from 'bar'` to: `import foo from './node_modules/bar/bar.js`.
### coverage
Due to a bug in karma, the test coverage reporter causes browser logs to appear twice which can be annoying
### compatibility
The compatibility option makes your code compatible with older browsers. It loads polyfills and transforms modern syntax where needed. For testing, it's best to leave this at 'none' for no modifications, or 'all' for full compatibility.
See [the documentation of the dev server](https://open-wc.org/developing/es-dev-server.html) for information on all the different modes.
## Karma preprocessors
Unfortunately, to make karma work with es modules regular karma preprocessors no longer work. You can, however, configure the `es-dev-server` to do code transformations if needed.
## Custom babel plugins
You can configure `karma-esm` to pick up the babel configuration files in your project:
```javascript
{
esm: {
@@ -93,6 +104,7 @@ You can configure `karma-esm` to pick up the babel configuration files in your p
```
## Testing typescript
The simplest way to test typescript is to compile your typescript to javascript before running tests. Just run `tsc` in watch mode and include the compiled js files from your karma config.
You can also configure `karma-esm` to run your typescript files directly. This is done by running it with a babel plugin to compile your typescript files to javascript.
@@ -100,20 +112,21 @@ You can also configure `karma-esm` to run your typescript files directly. This i
Note that when compiling typescript with babel it does not do any type checking or special typescript compilation such as decorators, class fields and enums. You can configure babel to cover most of these, but not all. [Read more about babel typescript here](https://babeljs.io/docs/en/babel-plugin-transform-typescript).
1. Install the preset:
```bash
npm i --save-dev @babel/preset-typescript
```
2. Add a `babel.config.js` or `.babelrc` to your project:
```json
{
"presets": [
"@babel/preset-typescript"
]
"presets": ["@babel/preset-typescript"]
}
```
3. Configure your karma config to pick up your ts files:
```javascript
{
files: [
@@ -130,17 +143,17 @@ npm i --save-dev @babel/preset-typescript
To add support for experimental features that are normally handled by the typescript compiler, you can add extra plugins:
1. Install the plugins:
1. Install the plugins:
```bash
npm i --save-dev @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties
```
2. Update your babel configuration:
2. Update your babel configuration:
```json
{
"presets": [
"@babel/preset-typescript"
],
"presets": ["@babel/preset-typescript"],
// for libraries that support babel decorators (lit-element) use:
"plugins": [
["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }],
@@ -154,7 +167,6 @@ npm i --save-dev @babel/plugin-proposal-decorators @babel/plugin-proposal-class-
}
```
<script>
export default {
mounted() {

View File

@@ -1,6 +1,6 @@
# Linting Prettier
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
Use [Prettier](https://prettier.io) to format your JS, CSS and HTML code.
@@ -9,6 +9,7 @@ This is part of the default [open-wc](https://open-wc.org/) recommendation
:::
## Setup
```bash
npm init @open-wc
# Upgrade > Linting
@@ -34,10 +35,7 @@ npm init @open-wc
- Update your `.eslintrc.js` to look like this:
```js
module.exports = {
extends: [
'@open-wc/eslint-config',
'eslint-config-prettier'
].map(require.resolve),
extends: ['@open-wc/eslint-config', 'eslint-config-prettier'].map(require.resolve),
};
```
@@ -51,6 +49,7 @@ npm init @open-wc
## Usage
Run:
- `npm run lint:prettier` to check if your files are correctly formatted
- `npm run format:prettier` to auto format your files

View File

@@ -1,10 +1,11 @@
# Rollup Plugin Index HTML
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
Rollup plugin to make rollup understand your index.html.
1. Takes in a standard index.html:
```html
<html lang="en-GB">
<head>
@@ -25,7 +26,7 @@ Rollup plugin to make rollup understand your index.html.
<my-app></my-app>
<script>
(function () {
(function() {
var message = 'hello inline script';
console.log(message);
})();
@@ -39,8 +40,25 @@ Rollup plugin to make rollup understand your index.html.
2. Extracts any `<script type="module" src="...">` and feeds them to rollup as entry point(s)
3. Outputs the same index.html with updated file hashes and all inline HTML, CSS and JS minified:
```html
<html lang="en-GB"><head><title>My app</title><style>my-app{display:block}</style></head><body><h1><span>Hello world!</span></h1><my-app></my-app><script>console.log("hello inline script");</script><script src="app.202933f045cc9f6cdf51.js"></script></body></html>
<html lang="en-GB">
<head>
<title>My app</title>
<style>
my-app {
display: block;
}
</style>
</head>
<body>
<h1><span>Hello world!</span></h1>
<my-app></my-app
><script>
console.log('hello inline script');</script
><script src="app.202933f045cc9f6cdf51.js"></script>
</body>
</html>
```
4. Optionally adds a loader script for conditionally loading polyfills and/or a separate build for older browsers.
@@ -48,6 +66,7 @@ Rollup plugin to make rollup understand your index.html.
Note that only module scripts with a `src` attribute are used as entrypoints, regular scripts and inline modules are minified but not parsed by rollup.
## Usage
To use this plugin, add it to your rollup configuration and set your index.html as entrypoint:
```js
@@ -56,15 +75,14 @@ const indexHTML = require('rollup-plugin-index-html');
module.exports = {
input: path.resolve(__dirname, './index.html'),
plugins: [
indexHTML(config),
],
plugins: [indexHTML(config)],
};
```
## Configuration
### Polyfills
> Note when using `@open-wc/building-rollup` many polyfills are already configured for you.
Depending on which browser you need to support you may need to polyfill certain browser features. To keep your bundles small, we don't serve any polyfills by default. You can enable polyfills in the configuration.
@@ -72,6 +90,7 @@ Depending on which browser you need to support you may need to polyfill certain
When enabling polyfills a small loader script is injected to your index.html. Polyfills are loaded based on feature detection. This causes a small delay in loading your app. We mediate this by adding a preload link during the build.
To enable polyfills:
```js
indexHTML({
polyfills: {
@@ -80,13 +99,14 @@ indexHTML({
webcomponents: true,
fetch: true,
intersectionObserver: true,
}
})
},
});
```
`core-js` polyfills many language features such as `Promise`, `Symbol` and `String.prototype.includes`. `regeneratorRuntime` is necessary when you compile `async await` code which is transpiled to javascript ES5. These two polyfills are mainly for supporting legacy browsers. They are only loaded on browsers which don't support modules, such as IE11.
The rest of the polyfills target specific browser features, see their documentation for more info:
- [core-js](https://github.com/zloirock/core-js)
- [regenerator-runtime](https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime)
- [webcomponents](https://github.com/webcomponents/webcomponentsjs)
@@ -94,6 +114,7 @@ The rest of the polyfills target specific browser features, see their documentat
- [intersection-observer](https://github.com/w3c/IntersectionObserver)
If you need a polyfill which is not on this list, consider creating an issue so that we can add it. You can also specify custom polyfills:
```js
indexHTML({
polyfills: {
@@ -111,10 +132,11 @@ indexHTML({
},
],
},
})
});
```
### Multi (legacy and modern) build
> Note when using `@open-wc/building-rollup/modern-and-legacy-config` the multi build is already configured for you
If you need to support non-modern browsers, such IE11 or older versions of chrome, safari and firefox, it's better to create multiple builds of your app.
@@ -137,7 +159,7 @@ module.exports = [
coreJs: true,
regeneratorRuntime: true,
webcomponents: true,
}
},
}),
],
},
@@ -166,25 +188,29 @@ For the legacy build you do not need to configure any polyfills, as these are al
You will probably need to use babel as well to transpile your code to ES5. Remember to change the browser targets for the modern and legacy build accordingly. For example latest 2 of the major browsers for modern and IE11 for the legac build.
### Minification
We use [html-minifier](https://github.com/kangax/html-minifier) for minifcation with a default configuration. You can adjust this configuration by passing a minify object:
```js
indexHTML({
minify: {
// minify options
}
})
},
});
```
The options object is passed as is to `html-minifier`. See the documentation of [html-minifier](https://github.com/kangax/html-minifier) for all possible minification options.
It is also possible to turn off minification completely by passing minify:
```js
indexHTML({
minify: false
})
minify: false,
});
```
### Non index.html entrypoints
You can use this plugin without an index.html plugin if you still want to make use of the polyfilling features. You can do this by adding a custom template function:
```js
@@ -213,6 +239,7 @@ module.exports = {
```
### CSP
When loading polyfills we inject a small script in your index.html. If you need CSP you can separate the script in a separate file:
```js
@@ -237,4 +264,5 @@ module.exports = {
],
};
```
The template function receives the project's `assets` and `entries`. If applicable it also receives the `legacyEntries` and `variation`.

View File

@@ -1,6 +1,6 @@
# Semantic Dom Diff
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
## Manual Setup

View File

@@ -1,6 +1,6 @@
# Testing Helpers
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
A library with helpers functions for testing in the browser.
@@ -9,6 +9,7 @@ A library with helpers functions for testing in the browser.
Testing helpers uses [lit-html](https://lit-html.polymer-project.org/), but it's set up as a peer dependency to avoid version conflicts.
You don't need to write your components with lit-html to use this library, but you will need to install it:
```bash
npm i -D lit-html
```
@@ -16,6 +17,7 @@ npm i -D lit-html
:::
# Usage
We recommend using this library through [@open-wc/testing](https://open-wc.org/testing/testing.html) which preconfigures and combines this library with other testing libraries.
The examples that are shown here assume this setup, and import from `@open-wc/testing`. If you want to use this library standalone, you will need to import from `@open-wc/testing-helpers` directly instead:
@@ -29,14 +31,17 @@ import { fixture } from '@open-wc/testing-helpers';
```
## Test fixtures
A test fixture renders a piece of HTML and injects into the DOM so that you can test the behavior of your component. It returns the first dom element from the template so that you can interact with it if needed. For example you can call functions, look up dom nodes or inspect the rendered HTML.
Test fixtures are async to ensure rendering is properly completed.
### Templates
Test fixtures can be set up by using a string or a [lit-html](https://github.com/Polymer/lit-html) template. You don't need to use `lit-html` in your project to use the test fixtures, it just renders standard HTML.
### Test a custom element
```js
import { fixture } from '@open-wc/testing';
@@ -47,50 +52,64 @@ it('can instantiate an element', async () => {
```
### Test a custom element with properties
```js
import { html, fixture } from '@open-wc/testing';
it('can instantiate an element with properties', async () => {
const el = await fixture(html`<my-el .foo=${'bar'}></my-el>`);
const el = await fixture(
html`
<my-el .foo=${'bar'}></my-el>
`,
);
expect(el.foo).to.equal('bar');
})
});
```
### Test a custom class
If you're testing a mixin, or have multiple base classes that offer a various set of options you might find yourself in the situation of needing multiple custom element names in your tests. This can be dangerous as custom elements are global, so you don't want to have overlapping names in your tests. We recommend using the `defineCE` function to avoid that:
```js
import { fixture, defineCE } from '@open-wc/testing';
const tag = defineCE(class extends MyMixin(HTMLElement) {
constructor() {
super();
this.foo = true;
}
});
const tag = defineCE(
class extends MyMixin(HTMLElement) {
constructor() {
super();
this.foo = true;
}
},
);
const el = await fixture(`<${tag}></${tag}>`);
expect(el.foo).to.be.true;
```
## Test a custom class with properties
For lit-html it's a little tougher as it does not support dynamic tag names by default.
This uses a workaround that's not performant for rerenders, which is fine for testing, but do NOT use this in production code.
```js
import { html, fixture, defineCE, unsafeStatic } from '@open-wc/testing';
const tagName = defineCE(class extends MyMixin(HTMLElement) {
constructor() {
super();
this.foo = true;
}
});
const tagName = defineCE(
class extends MyMixin(HTMLElement) {
constructor() {
super();
this.foo = true;
}
},
);
const tag = unsafeStatic(tagName);
const el = await fixture(html`<${tag} .bar=${'baz'}></${tag}>`);
expect(el.bar).to.equal('baz');
```
## Timings
By default fixture awaits the elements "update complete" Promise.
- for [lit-element](https://github.com/polymer/lit-element) that is `el.updateComplete`;
- for [stencil](https://github.com/ionic-team/stencil/) that is `el.componentOnReady()`;
@@ -100,25 +119,38 @@ If none of those specfic Promise hooks are found, it will wait for one frame via
Essentially, `fixture` creates a synchronous fixture, then waits for the element to finish updating, checking `updateComplete` first, then falling back to `componentReady()`, and `nextFrame()` as a last resort.
This way, you can write your tests more succinctly, without having to explicitly `await` those hooks yourself.
```js
const el = await fixture(html`<my-el .foo=${'bar'}></my-el>`);
const el = await fixture(
html`
<my-el .foo=${'bar'}></my-el>
`,
);
expect(el.foo).to.equal('bar');
// vs
const el = fixtureSync(html`<my-el .foo=${'bar'}></my-el>`);
const el = fixtureSync(
html`
<my-el .foo=${'bar'}></my-el>
`,
);
await elementUpdated(el);
expect(el.foo).to.equal('bar');
```
### nextFrame
Uses `requestAnimationFrame` to wait for the next frame.
```js
await nextFrame();
```
### aTimeout
Waits for `x` ms via `setTimeout`;
```js
await aTimeout(10); // would wait 10ms
```
@@ -138,16 +170,17 @@ describe('Attributes', () => {
const el = await fixture('<my-component title="test"></my-component>');
expect(el.title).to.eq('test');
el.title = "test 2"
await elementUpdated(el)
el.title = 'test 2';
await elementUpdated(el);
expect(el).dom.to.equal(`<my-component title="test 2"></my-component>`);
});
//...
})
});
});
```
## Testing Events
If you want to interact with web components you will sometimes need to await a specific event before you can continue testing.
Ordinarily, you might pass the `done` callback to a test, and call it in the body of an event handler.
This does not work with async test functions, though, which must return a promise instead of calling the `done` callback.
@@ -179,6 +212,7 @@ it('can await an event', async () => {
```
## Testing Focus & Blur on IE11
Focus and blur events are synchronous events in all browsers except IE11.
If you need to support that browser in your tests, you can await `triggerFocusFor` and `triggerBlurFor` helper functions.
@@ -197,8 +231,10 @@ it('can be focused and blured', async () => {
```
## Fixture Cleanup
By default, if you import anything via `import { ... } from '@open-wc/testing';`, it will automatically register a side-effect that cleans up your fixtures.
If you want to be in full control you can do so by using
```js
import { fixture, fixtureCleanup } from '@open-wc/testing-helpers/index-no-side-effects.js';

View File

@@ -1,6 +1,6 @@
# Testing via Browserstack
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
To make sure your project is production-ready, we recommend running tests in all the browsers you want to support.
@@ -10,13 +10,17 @@ Browserstack offers free accounts for [open source projects](https://www.browser
The `testing-karma-bs` configuration helps setting up karma with Browserstack. To set it up you need to use the configuration in your project, and follow the instructions below to set up a user account
## Setup
With our project scaffolding you can set up a pre-configured project, or you can upgrade an existing project by choosing `Upgrade -> Testing`:
```bash
npm init @open-wc
```
### Manual
Install:
```bash
npm i -D @open-wc/testing-karma-bs deepmerge
```
@@ -42,6 +46,7 @@ module.exports = config => {
```
Add a script to your `package.json`:
```json
{
"scripts": {
@@ -51,6 +56,7 @@ Add a script to your `package.json`:
```
### Setup user + key
- Go to [https://www.browserstack.com/accounts/settings](https://www.browserstack.com/accounts/settings)
- Look for "Automate" and write down your "Access Key" and "Username"
@@ -69,6 +75,7 @@ echo "Key: $BROWSER_STACK_ACCESS_KEY"
```
### Usage
```bash
npm run test:bs
```

View File

@@ -1,6 +1,6 @@
# Testing with Karma
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
We recommend karma as a general-purpose tool for testing code which runs in the browser. Karma can run a large range of browsers, including IE11. This way you are confident that your code runs correctly in all supported environments.
@@ -9,11 +9,13 @@ During development you can run Chrome Headless, giving fast feedback in the term
Karma can be used both for running unit tests, as well as for running more complex e2e/integration tests in the DOM.
## Getting started
Our configuration sets up karma to run tests based on es modules with the necessary polyfills and fallbacks for older browsers and convenient test reporting.
This page explains how to set up `karma`, see the [testing overview](https://open-wc.org/testing/) for guides and libraries to get started with testing in general.
### Features
- Runs tests with es modules
- Serves static files
- Runs tests through mocha
@@ -22,18 +24,23 @@ This page explains how to set up `karma`, see the [testing overview](https://ope
- Supports older browsers (down to IE11) when passing the `compatibility` flag
## Setup
With our project scaffolding you can set up a pre-configured project, or you can upgrade an existing project by choosing `Upgrade -> Testing`:
```bash
npm init @open-wc
```
### Manual
Install:
```bash
npm i -D @open-wc/testing-karma deepmerge karma
```
Create a `karma.conf.js`:
```js
const { createDefaultConfig } = require('@open-wc/testing-karma');
const merge = require('deepmerge');
@@ -47,21 +54,22 @@ module.exports = config => {
//
// npm run test -- --grep test/foo/bar.test.js
// npm run test -- --grep test/bar/*
{ pattern: config.grep ? config.grep : 'test/**/*.test.js', type: 'module' }
{ pattern: config.grep ? config.grep : 'test/**/*.test.js', type: 'module' },
],
// see the karma-esm docs for all options
esm: {
// if you are using 'bare module imports' you will need this option
nodeResolve: true
}
})
nodeResolve: true,
},
}),
);
return config;
};
```
Add scripts to your package.json:
```json
{
"scripts": {
@@ -75,7 +83,9 @@ Add scripts to your package.json:
```
## Workflow
Commands explained:
- `test`: does a single test run on the configured browsers (default headless chrome) and prints tests and coverage results.
- `test:watch`: does a single test run, and then re-runs on file changes. coverage is not analyzed for performance. in watch mode you can also visit http://localhost:9876/debug.html to debug in the browser
- `test:update-snapshots`: updates any snapshots files from `@open-wc/semantic-dom-diff`. Use this when your component's rendered HTML changed.
@@ -83,11 +93,13 @@ Commands explained:
- `test:compatibility`: like `test:watch`, except that it makes your tests compatible with older browsers (including IE11).
## Testing single files or folders
By default, karma runs all your test files. To test a single file or folder, use the `--grep` flag. (If you did a manual setup, makes sure your config handles this flag).
Pass which files to test to the grep flag: `npm run test -- --grep test/foo/bar.test.js`.
## Debugging in the browser
While testing, it can be useful to debug your tests in a real browser so that you can use the browser's dev tools.
Use `npm run test:watch` to keep karma running. Then open the URL printed by karma when it boots up. By default, this is `http://localhost:9876/`. Click the debug button in the top right corner, or go directly to `http://localhost:9876/debug.html`.
@@ -97,12 +109,13 @@ You can bookmark this page for easy access.
Adding `debugger` statements will allow you to debug using the browser's dev tools.
## Testing on older browsers
By default, our configuration does not do any modifications to your code. It just runs it as is in the browser. Depending on which features you use, this should be fine for most major browsers.
By passing the `compatibility` flag, we enable compatibility mode which makes your code run on older browsers as well. It loads polyfills and transforms modern syntax where needed. There are a few possible modes, but generally 'all' is sufficient for testing. This mode is powered by `karma-esm`. [Check out the documentaton](https://open-wc.org/testing/karma-esm.html) for more information.
## Why don't you recommend testing tool X?
Sometimes people ask why we recommend Karma and not other popular testing tools. We're always on the lookout for improving our recommendations, so if you think we can do better please let us know. What's important for us is that the testing tool is robust, simple to use, does not require any building and runs in a real browser.
Testing tools that don't use a real browser but something like jsdom constantly need to keep up with the latest browser standards, so you need to wait for your testing tool to update before you can use a new feature. It doesn't give the same confidence as testing in a real browser, and with Headless Chrome and Puppeteer it hardly seems necessary anymore.
@@ -124,7 +137,7 @@ module.exports = config => {
//
// npm run test -- --grep test/foo/bar.test.js
// npm run test -- --grep test/bar/*
{ pattern: config.grep ? config.grep : 'test/**/*.test.js', type: 'module' }
{ pattern: config.grep ? config.grep : 'test/**/*.test.js', type: 'module' },
],
coverageIstanbulReporter: {
@@ -144,14 +157,17 @@ module.exports = config => {
```
### Custom babel plugins or typescript support
`karma-esm` supports custom babel configurations and typescript. [Check out the documentaton](https://open-wc.org/testing/karma-esm.html) for more information.
### Testing in a monorepository
When testing without a bundler you will be serving every imported module straight from the file system. Karma cannot serve files outside the path of the webserver, which by default starts from the directory of your karma config.
In a monorepo dependencies are often two levels higher in the root of the repository. To run tests in a monorepository you either have to put your config in the root of the repository, or adjust the basePath in your karma config:
### Other configuration
`karma-esm` is the plugin powering our configuration, and it supports a few more for advanced use cases. [Check out the documentaton](https://open-wc.org/testing/karma-esm.html) for more information.
```js
@@ -161,9 +177,7 @@ const merge = require('deepmerge');
module.exports = config => {
config.set(
merge(createDefaultConfig(config), {
files: [
{ pattern: config.grep ? config.grep : 'test/**/*.test.js', type: 'module' }
],
files: [{ pattern: config.grep ? config.grep : 'test/**/*.test.js', type: 'module' }],
basePath: '../../',
}),

View File

@@ -1,25 +1,30 @@
# Testing in IDE via Wallaby
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
Wallaby.js is a Plugin for your IDE and runs tests in real time while you are typing.
Using:
- In IDE Testing via [wallaby.js](https://wallabyjs.com/)
## Setup
```bash
npm init @open-wc
```
### Manual
1. Copy the [config](https://github.com/open-wc/open-wc/blob/master/packages/create/src/generators/testing-wallaby/templates/static/wallaby.js) and save it as `wallaby.js` into your project root
2. `npm i -D @open-wc/testing-wallaby`
## Usage
Open your wallaby.js supported IDE and start with the provided config.
## Example
The [Set-Game Example](https://github.com/open-wc/example-vanilla-set-game/) has Wallaby Setup.
<script>

View File

@@ -1,6 +1,6 @@
# Testing
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
An opinionated package that combines and configures testing libraries to minimize the amount of ceremony required when writing tests.

View File

@@ -1,13 +1,15 @@
# Webpack Helpers
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
If you need support to use `import.meta` within webpack this is a minimal loader to support it.
## Note
This is NOT an optimal solution e.g. it may slow down your build a little.
However as currently `import.meta` results in an webpack parse error using a loader is probably the only thing we can do for now.
For details see
For details see
- [https://github.com/webpack/webpack/issues/6719](https://github.com/webpack/webpack/issues/6719)
- [https://github.com/Polymer/tools/issues/518](https://github.com/Polymer/tools/issues/518)
@@ -15,8 +17,10 @@ If webpack fixed that parse error import.meta will probably work out of the box.
If not then a babel plugin (that can work with AST) will be a better solution.
## Manual Setup
- `yarn add @open-wc/webpack-import-meta-loader`
- Add this to your webpack config
```js
module: {
rules: [

View File

@@ -1,10 +1,11 @@
# Webpack Index HTML Plugin
[//]: # (AUTO INSERT HEADER PREPUBLISH)
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
Webpack plugin to make webpack understand your index.html.
1. Takes in a standard index.html:
```html
<html lang="en-GB">
<head>
@@ -25,7 +26,7 @@ Webpack plugin to make webpack understand your index.html.
<my-app></my-app>
<script>
(function () {
(function() {
var message = 'hello inline script';
console.log(message);
})();
@@ -39,8 +40,25 @@ Webpack plugin to make webpack understand your index.html.
2. Extracts any `<script type="module" src="...">` and feeds them to webpack as entry point(s)
3. Outputs the same index.html with updated file hashes and all inline HTML, CSS and JS minified:
```html
<html lang="en-GB"><head><title>My app</title><style>my-app{display:block}</style></head><body><h1><span>Hello world!</span></h1><my-app></my-app><script>console.log("hello inline script");</script><script src="app.202933f045cc9f6cdf51.js"></script></body></html>
<html lang="en-GB">
<head>
<title>My app</title>
<style>
my-app {
display: block;
}
</style>
</head>
<body>
<h1><span>Hello world!</span></h1>
<my-app></my-app
><script>
console.log('hello inline script');</script
><script src="app.202933f045cc9f6cdf51.js"></script>
</body>
</html>
```
4. Optionally adds a loader script for conditionally loading polyfills and/or a separate build for older browsers.
@@ -48,6 +66,7 @@ Webpack plugin to make webpack understand your index.html.
Note that only module scripts with a `src` attribute are used as entrypoints, regular scripts and inline modules are minified but not parsed by webpack.
## Usage
To use this plugin, add it to your webpack configuration and set your index.html as entrypoint:
```js
@@ -62,16 +81,14 @@ module.exports = {
chunkFilename: '[name].[chunkhash].js',
},
plugins: [
new WebpackIndexHTMLPlugin(),
],
plugins: [new WebpackIndexHTMLPlugin()],
};
```
## Configuration
### Polyfills
> Note when using `@open-wc/building-webpack` polyfills are already configured for you.
Depending on which browser you need to support you may need to polyfill certain browser features. To keep your bundles small, we don't serve any polyfills by default. You can enable polyfills in the configuration.
@@ -79,6 +96,7 @@ Depending on which browser you need to support you may need to polyfill certain
When enabling polyfills a small loader script is injected to your index.html. Polyfills are loaded based on feature detection. This causes a small delay in loading your app. We mediate this by adding a preload link during the build.
To enable polyfills:
```js
new WebpackIndexHTMLPlugin({
polyfills: {
@@ -88,13 +106,14 @@ new WebpackIndexHTMLPlugin({
webcomponents: true,
fetch: true,
intersectionObserver: true,
}
})
},
});
```
`core-js` polyfills many language features such as `Promise`, `Symbol` and `String.prototype.includes`. `regeneratorRuntime` is necessary when you compile `async await` code which is transpiled to javascript ES5. These two polyfills are mainly for supporting legacy browsers. They are only loaded on browsers which don't support modules, such as IE11.
The rest of the polyfills target specific browser features, see their documentation for more info:
- [core-js](https://github.com/zloirock/core-js)
- [regenerator-runtime](https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime)
- [webcomponents](https://github.com/webcomponents/webcomponentsjs)
@@ -102,6 +121,7 @@ The rest of the polyfills target specific browser features, see their documentat
- [intersection-observer](https://github.com/w3c/IntersectionObserver)
If you need a polyfill which is not on this list, consider creating an issue so that we can add it. You can also specify custom polyfills:
```js
new WebpackIndexHTMLPlugin({
polyfills: {
@@ -125,6 +145,7 @@ You can disable the content hash in the distributed polyfill filenames by settin
```
### Multi (legacy and modern) build
> Note when using `@open-wc/building-webpack/modern-and-legacy-config` the multi build is already configured for you
If you need to support non-modern browsers, such IE11 or older versions of chrome, safari and firefox, it's better to create multiple builds of your app.
@@ -147,7 +168,7 @@ module.exports = [
coreJs: true,
regeneratorRuntime: true,
webcomponents: true,
}
},
}),
],
},
@@ -176,25 +197,29 @@ For the legacy build you do not need to configure any polyfills, as these are al
You will probably need to use babel as well to transpile your code to ES5. Remember to change the browser targets for the modern and legacy build accordingly. For example latest 2 of the major browsers for modern and IE11 for the legac build.
### Minification
We use [html-minifier](https://github.com/kangax/html-minifier) for minifcation with a default configuration. You can adjust this configuration by passing a minify object:
```js
new WebpackIndexHTMLPlugin({
minify: {
// minify options
}
})
},
});
```
The options object is passed as is to `html-minifier`. See the documentation of [html-minifier](https://github.com/kangax/html-minifier) for all possible minification options.
It is also possible to turn off minification completely by passing minify:
```js
new WebpackIndexHTMLPlugin({
minify: false
})
minify: false,
});
```
### Non index.html entrypoints
You can use this plugin without an index.html plugin if you still want to make use of the polyfilling features. You can do this by adding a custom template function:
```js
@@ -223,6 +248,7 @@ module.exports = {
```
### CSP
When loading polyfills we inject a small script in your index.html. If you need CSP you can separate the script in a separate file:
```js
@@ -247,4 +273,5 @@ module.exports = {
],
};
```
The template function receives the project's `assets` and `entries`. If applicable it also receives the `legacyEntries` and `variation`.