web componentでHello World
WEB+DBで記事の特集をしていたので試してみた。
ビルド環境の作成にはdockerを使用。
ついでに、angularやelmなども試した。
サイズ比較
Hello worldを表示するだけのWeb Componentでの比較なので、
ほぼライブラリ部分の容量。
vagrant@ubuntu-bionic[master]: $ ls ../server/dist/ -alh
total 448K
drwxrwxrwx 1 vagrant vagrant 0 May 10 08:33 .
drwxrwxrwx 1 vagrant vagrant 0 May 10 08:33 ..
-rwxrwxrwx 1 vagrant vagrant 3.2K May 10 20:55 tsApp.js
-rwxrwxrwx 1 vagrant vagrant 26K May 10 20:56 elmApp.js
-rwxrwxrwx 1 vagrant vagrant 79K May 10 20:57 vueApp.js
-rwxrwxrwx 1 vagrant vagrant 120K May 10 20:47 reactApp.js
-rwxrwxrwx 1 vagrant vagrant 215K May 10 08:07 angularApp.js
記述比較
Vue
vue-app/src/App.vue
<template>
<div>
<p>Vue-app</p>
</div>
</template>
vue-app/src/index.js
import Vue from 'vue';
import App from './App';
import vueCustomElement from 'vue-custom-element';
Vue.use(vueCustomElement);
Vue.customElement('vue-app', App);
React
react-app/src/index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render() {
return <div>React-app</div>;
}
}
// Custom ElementとするためにHTMLElementを継承
class CustomElementsApp extends HTMLElement {
connectedCallback() {
const mountPoint = document.createElement('div');
this.attachShadow({ mode: 'open' }).appendChild(mountPoint);
ReactDOM.render(<App />, mountPoint);
}
}
customElements.define('react-app', CustomElementsApp);
Elm
elm-app/src/App.elm
module App exposing (main)
import Html exposing (Html, text)
main : Html msg
main =
text "Elm App"
elm-app/src/index.js
const { Elm } = require("./App.elm");
class ElmApp extends HTMLElement {
connectedCallback() {
Elm.App.init({ node: this });
}
}
customElements.define("elm-app", ElmApp);
Angular
angular-app/src/app.component.ts
import { Component, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { HelloComponent } from './hello/hello.component';
@Component({
selector: 'angular-app',
template: ``,
})
export class AppComponent {
constructor(
private injector: Injector,
) {
const AppHelloElement = createCustomElement(
HelloComponent,
{ injector: this.injector }
);
customElements.define('angular-app', AppHelloElement);
}
}
angular-app/src/app/hello/hello.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-hello',
templateUrl: './hello.component.html',
styleUrls: ['./hello.component.css']
})
export class HelloComponent {
title = 'angular-app';
}
angular-app/src/app/hello/hello.component.html
<!--The content below is only a placeholder and can be replaced.-->
<div>
{{ title }}!
</div>
angular-app/src/app/app.module.ts
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello/hello.component';
@NgModule({
imports: [BrowserModule, FormsModule],
declarations: [AppComponent, HelloComponent],
bootstrap: [AppComponent],
entryComponents: [HelloComponent]
})
export class AppModule { }
angular-app/src/main.ts
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
Typescript
ts-app/src/index.ts
class TsApp extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
const wrapper = document.createElement('span');
wrapper.setAttribute('class', 'wrapper');
const info = document.createElement('span');
info.setAttribute('class', 'info');
info.textContent = 'ts-app';
shadow.appendChild(wrapper);
wrapper.appendChild(info);
}
}
customElements.define('ts-app', TsApp);
ひっかかったところ
angularは最新版のtsやcore-jsではエラーとなるらしい。。
あとコンテナにchromeが入っていなかったのでインストール。これはkarma用。
angular-app/docker/angular/Dockerfile
FROM node:11.15.0
# コンテナ上の作業ディレクトリ作成
WORKDIR /app
RUN yarn add --dev \
@angular/compiler-cli \
@angular-devkit/build-angular \
@angular/cli \
@angular/language-service \
@types/jasmine \
@types/jasminewd2 \
@types/node \
codelyzer \
jasmine-core \
jasmine-spec-reporter \
karma \
karma-chrome-launcher \
karma-coverage-istanbul-reporter \
karma-jasmine \
karma-jasmine-html-reporter \
protractor \
ts-node \
tslint
RUN yarn add \
@angular/animations \
@angular/common \
@angular/compiler \
@angular/core \
@angular/elements \
@angular/forms \
@angular/http \
@angular/platform-browser \
@angular/platform-browser-dynamic \
@angular/router \
rxjs \
zone.js \
document-register-element
# ERROR in The Angular Compiler requires TypeScript >=3.1.1 and <3.3.0 but 3.4.5 was found instead.
RUN yarn add --dev typescript@3.2.x
# core-js 3.0系だとエラー
RUN yarn add core-js@2.6.x
# test用
RUN \
apt-get update && \
apt-get install -y wget curl unzip apt-utils && \
mkdir -p /home/root/src && cd $_ && \
wget -q -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip && \
unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/ && \
apt-get install -y libappindicator1 fonts-liberation libasound2 libnspr4 libnss3 libxss1 lsb-release xdg-utils && \
touch /etc/default/google-chrome && \
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN apt-get install -y libappindicator3-1 \
libatk-bridge2.0-0 \
libatspi2.0-0 \
libgtk-3-0
RUN cd /home/root/src && wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && dpkg -i google-chrome-stable_current_amd64.deb && \
apt-get install -y fonts-migmix
参考
WEB+DB PRESS vol.110
単一コンポーネントのエラーの」解決
Docker Composeを使ってサクッとNginxコンテナを起動する
Elm と他のフレームワークを組み合わせる
npm
angular component
docker-composeでangular-cliの環境を作ってみる
Dockerでheadless-chromeを使ったスクレイピング環境を整える
UbuntuにChromeをインストールする
karma headless chrome
lit-htmlとバニラWeb Componentsでコンポーネントを実装する
“Web Componentsだけ” で新サービスを実装して見えたこと