Angular4 + Django1.11 vol.7
参考サイト
https://www.codingforentrepreneurs.com/projects/angular-django/ http://qiita.com/kura07/items/c9fa858870ad56dfec12
Handling 404 with Object Lookups
指定したurlが無いときの、404 errorのページを設定する。
video-detail.component.ts を修正する。
ngOnInit() { this.routeSub = this.route.params.subscribe(params => { this.slug = params['slug'] this.req = this._video.get(this.slug).subscribe(data=>{ this.video = data as VideoItem }, error=>{ // subscribeがrrorの場合の内容をconsole.logに表示する console.log(error) // }) }) }
- 実際にerrorが出るpageにアクセスしてみると以下のようなerrorがconsoleに表示される。
eaders:t ok:false status:404 statusText:"Not Found" type:2 url:"http://127.0.0.1:8000/api/videos/bound-method-videotitle-/" _body:"{"detail":"Not found."}"
- videos.service.ts にalertが出るように追記する。
private handleError(error:any, caught:any): any{ console.log(error, caught) if (error.status == 404){ // statusが、404のときに、alertが表示されるように設定する alert("Oopps. Not found") } }
- さらに、errorがでたときには、video一覧に戻るようにrouterを設定する。設定するのは、video-detail.component.typescript.
import { ActivatedRoute, Router } from '@angular/router'; // Routerをimport import { VideoItem } from '../videos/video'; import { VideoService } from '../videos/videos.service'; ... ... constructor(private route: ActivatedRoute, private router: Router, private _video:VideoService) { } // constructorにprivate router: Routerで型定義する。 ngOnInit() { this.routeSub = this.route.params.subscribe(params => { this.slug = params['slug'] this.req = this._video.get(this.slug).subscribe(data=>{ this.video = data as VideoItem }, error=>{ console.log(error) this.router.navigate(['/videos']) // subscribeがerrorのときに、/videos にアクセスする。 }) }) }
- errorのときの処理をさらに修正する。
export class VideoDetailComponent implements OnInit, OnDestroy { private routeSub:any; private req:any; video: VideoItem; slug:string; error: Boolean; //errorの型定義をする constructor(private route: ActivatedRoute, private router: Router, private _video:VideoService) { } ngOnInit() { this.routeSub = this.route.params.subscribe(params => { this.slug = params['slug'] this.req = this._video.get(this.slug).subscribe(data=>{ this.video = data as VideoItem }, error=>{ console.log(error) this.error = true; // errorがでたときには、errorをtrueにする。 // this.router.navigate(['/videos']) }) }) } }
- video-detail.component.htmlに追記する。
<div *ngIf='!video && !error'>Loading</div> <div *ngIf='error'>Error. Please try again.</div>
まとめ
- errorは、subscribeのerror時の処理を使うと良さそう。
Angular4 + Django1.11 vol.6
参考サイト
https://www.codingforentrepreneurs.com/projects/angular-django/ http://www.django-rest-framework.org/api-guide/generic-views/#listapiview http://qiita.com/kura07/items/c9fa858870ad56dfec12
Better Backend Queries
- featuredのqueryをmodelsでやるようにする。
from django.db import models from django.db.models.signals import pre_save # Create your models here. from .utils import unique_slug_generator class VideoQuerySet(models.query.QuerySet): # models.query.QuerySetを継承した、VideoQuerySet classを作成する def featured(self): # featuredメソッドを追加する。 return self.filter(featured=True) # featuredメソッドは、querysetにfeatured=Trueのfilterをかけて、その結果を返す。 class VideoManager(models.Manager): #models.Managerを継承したVideoManagerClassを作成する。 def get_queryset(self): # get_querysetで、VideoQuerySetのinstanceを返すようにセットする。 return VideoQuerySet(self, using=self._db) def featured(self): return self.get_queryset().featured() # featuredメソッドは、VideoQuerySetのfeaturedメソッドの値を返すメソッド。 class Video(models.Model): name = models.CharField(max_length=220) slug = models.SlugField(unique=True, blank=True) embed = models.CharField(max_length=120, help_text='Youtube Embed Code', null=True, blank=True) featured = models.BooleanField(default=False) timestamp = models.DateTimeField(auto_now_add=True) objects = VideoManager() # objectsには、VideoManagerのinstanceを代入する。 def __str__(self): return self.name def title(self): return self.name def video_pre_save_receiver(sender, instance, *args, **kwargs): if not instance.slug: instance.slug = unique_slug_generator(instance) pre_save.connect(video_pre_save_receiver, sender=Video)
- views.pyを以下のように修正する。
class VideoFeatured(generics.ListAPIView): queryset = Video.objects.all() serializer_class = VideoSerializer permission_classes = [] authentication_classes = [] def get_queryset(self): query = self.request.GET.get("q") if query: qs = Video.objects.filter(name__icontains=query).featured() else: qs = Video.objects.featured() return qs
- 次はsearchメソッドを追記する。まずは、models.pyにsearchメソッドを追加する。
from django.db.models import Q ... class VideoQuerySet(models.query.QuerySet): def featured(self): return self.filter(featured=True) def search(self, query): return self.get_queryset().filter( Q(name__icontains=query) | Q(slug__icontains=query) | Q(embed__icontains=query) ) class VideoManager(models.Manager): def get_queryset(self): return VideoQuerySet(self.model, using=self._db) def featured(self): return self.get_queryset().featured() def search(self, query): return self.get_queryset().search(query)
- views.pyに追記する。
class VideoList(generics.ListAPIView): queryset = Video.objects.all() serializer_class = VideoSerializer permission_classes = [] authentication_classes = [] def get_queryset(self): query = self.request.GET.get("q") if query: # qs = Video.objects.filter(name__icontains=query) qs = Video.objects.search(query) else: qs = Video.objects.all() return qs class VideoFeatured(generics.ListAPIView): queryset = Video.objects.all() serializer_class = VideoSerializer permission_classes = [] authentication_classes = [] def get_queryset(self): query = self.request.GET.get("q") if query: qs = Video.objects.featured().search(query) else: qs = Video.objects.featured() return qs
- activeフィールドも追加して、最終的にmodels.pyは以下のようになった。
from django.db import models from django.db.models import Q from django.db.models.signals import pre_save # Create your models here. from .utils import unique_slug_generator class VideoQuerySet(models.query.QuerySet): def active(self): return self.filter(active=True) def featured(self): return self.filter(featured=True) def search(self, query): return self.get_queryset().filter( Q(name__icontains=query) | Q(slug__icontains=query) | Q(embed__icontains=query) ) class VideoManager(models.Manager): def get_queryset(self): return VideoQuerySet(self, using=self._db) def all(self): return self.get_queryset().active() def featured(self): return self.get_queryset().featured().active() def search(self, query): return self.get_queryset().search(query).active() class Video(models.Model): name = models.CharField(max_length=220) slug = models.SlugField(unique=True, blank=True) embed = models.CharField(max_length=120, help_text='Youtube Embed Code', null=True, blank=True) active = models.BooleanField(default=True) featured = models.BooleanField(default=False) timestamp = models.DateTimeField(auto_now_add=True) objects = VideoManager() def __str__(self): return self.name def title(self): return self.name def video_pre_save_receiver(sender, instance, *args, **kwargs): if not instance.slug: instance.slug = unique_slug_generator(instance) pre_save.connect(video_pre_save_receiver, sender=Video)
- error 発生!
_meta
がmanagerにはないとのこと。どうもquerysetの箇所を以下のように修正する必要があるようだ。
class VideoManager(models.Manager): def get_queryset(self): return VideoQuerySet(self.model, using=self._db)
まとめ
- VideoManager と、VideoQuerySetをsetで使うと、better queryを作成できる。こちらの方がrobustのようだ。確かに、queryは、modelで完結させたほうが、わかりやすい気がする。
Angular4 + Django1.11 vol.5
参考サイト
https://www.codingforentrepreneurs.com/projects/angular-django/ http://www.django-rest-framework.org/api-guide/generic-views/#listapiview http://qiita.com/kura07/items/c9fa858870ad56dfec12
Integrate Django API with Angular
const endpoint = '/api/videos/'
- お〜〜表示された!すげー!
Detail View
- detail viewを作成するために、まずは api/views.pyに、RetrieveAPIViewを追加する。
from django.contrib.auth.models import User from rest_framework import generics from rest_framework.permissions import IsAdminUser from videos.models import Video from .serializers import VideoSerializer class VideoList(generics.ListAPIView): queryset = Video.objects.all() serializer_class = VideoSerializer permission_classes = [] authentication_classes = [] class VideoDetail(generics.RetrieveAPIView): queryset = Video.objects.all() serializer_class = VideoSerializer permission_classes = [] authentication_classes = []
- 次に、urls.pyにdetail viewのurlを追加する。
from django.conf.urls import url from .views import VideoList, VideoDetail urlpatterns = [ url(r'^$', VideoList.as_view(), name='list'), url(r'^(?P<slug>[\w-]+)/$', VideoDetail.as_view()), ] # ここでは、slugからvideoDetailをgetするようにセットしてある
http://127.0.0.1:8000/api/videos/bound-method-videotitle-of-video-new-title/
にアクセスしてみる。。。error発生!
AssertionError at /api/videos/bound-method-videotitle-of-video-new-title/ Expected view VideoDetail to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.
- lookup_fieldのセットが必要ぽいので、セットする。
class VideoDetail(generics.RetrieveAPIView): queryset = Video.objects.all() serializer_class = VideoSerializer lookup_field = "slug" permission_classes = [] authentication_classes = []
これだけで修正完了(^^)すごい!
VideoDetail用のVideoDetailSerializerも作成する。
class VideoDetailSerializer(serializers.ModelSerializer): image = serializers.SerializerMethodField() is_promo = serializers.SerializerMethodField() class Meta: model = Video fields = [ 'name', 'slug', 'embed', 'featured', 'image', 'is_promo' ] def get_image(self,obj): return "/static/ang/assets/images/nature/4.jpg" def get_is_promo(self,obj): return False
VideoDetailに、
serializer_class=VideoDetailSerializer
を、セットすれば完了。videos.service.tsのget(slug)メソッドを修正する。
get(slug){ return this.http.get(endpoint + slug + "/") // endpoint + slug + "/"に設定する。 .map(response=>response.json()) .catch(this.handleError) // return this.http.get(endpoint) // .map(response=>{ // let data = response.json().filter(item=>{ // if (item.slug == slug) { // return item // } // }) // if (data.length == 1){ // return data[0] // } // return {} // }) // .catch(this.handleError) }
Backend API Search
- backendのdjangoに、Search後のqueryを出力する機能をつける。
class VideoList(generics.ListAPIView): queryset = Video.objects.all() serializer_class = VideoSerializer permission_classes = [] authentication_classes = [] def get_queryset(self): query = self.request.GET.get("q") if query: qs = Video.objects.filter(name__icontains=query) else: qs = Video.objects.all() return qs
http://127.0.0.1:8000/api/videos/?q=new
になどのようにアクセスして、検索結果が表示されればOK(^^)videos.service.ts のsearch(query)メソッドのendpointを修正する。以下のように予想した。
search(query){ return this.http.get(endpoint + "?q=" + query) .map(response=>response.json()) .catch(this.handleError) }
- 上記でも動く気がするんだけど、動画内では以下のように記載していた。
search(query){ let querystring = `?q=${query}` return this.http.get(endpoint + querystring) .map(response=>response.json()) .catch(this.handleError) // return this.http.get(endpoint) // .map(response=>{ // let data = [] // let req = response.json().filter(item=>{ // if (item.name.indexOf(query) >=0) { // data.push(item) // } // }) // // return data // }) // .catch(this.handleError) }
- videos.service.tsは以下の通りに全体を修正したある。
import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; // const endpoint = '/static/ang/assets/json/videos.json' // http://www.yourdomain.com/api/videos/ const endpoint = '/api/videos/' @Injectable() export class VideoService { constructor(private http: Http) { } list(){ return this.http.get(endpoint) .map(response=>response.json()) .catch(this.handleError) } get(slug){ return this.http.get(endpoint + slug + "/") .map(response=>response.json()) .catch(this.handleError) } search(query){ let querystring = `?q=${query}` return this.http.get(endpoint + querystring) .map(response=>response.json()) .catch(this.handleError) } private handleError(error:any, caught:any): any{ console.log(error, caught) } }
- home.component.ts の、featuredされたitemのみを表示するという機能もbackendに移行させる。
ngOnInit() { this.req = this._video.featured().subscribe(data=>{ //console.log(data.json()) //this.homeImageList this.homeImageList = data as [VideoItem] // data.filter(item=>{ // if(item.featured){ // let dataItem = item // this.homeImageList.push(dataItem) // } // }) // this.homeImageList = data.json(); }) }
- featuredメソッドは、まだ定義されていないので、videos.service.tsに追加する。
featured(){ return this.http.get(endpoint + "featured/") .map(response=>response.json()) .catch(this.handleError) }
- backendのdjangoに、featured のurlを作成していないので、設定する。
lass VideoFeatured(generics.ListAPIView): queryset = Video.objects.all() serializer_class = VideoSerializer permission_classes = [] authentication_classes = [] def get_queryset(self): query = self.request.GET.get("q") if query: qs = Video.objects.filter(name__icontains=query).filter(featured=True) else: qs = Video.objects.filter(featured=True) return qs
- urls.py に、featured viewのurlをセットする。
from django.conf.urls import url from .views import VideoList, VideoDetail, VideoFeatured urlpatterns = [ url(r'^$', VideoList.as_view(), name='list'), url(r'^featured/$', VideoFeatured.as_view(), name='featured'), url(r'^(?P<slug>[\w-]+)/$', VideoDetail.as_view()), ]
http://127.0.0.1:8000/api/videos/featured/
にアクセスして、rest_framework viewが表示されればOK(^^)
まとめ
endpointから必要なデータを取得して、client側では加工しないほうが、シンプルな実装ができそうだな。frontendとbackendを分けるメリットはこのへんにあるのか。
let querystring =
?q=${query}
については、ちゃんと意味を調べないとな。。とりあえず、バッククオートは、複数行のコメントをするときに便利らしい。あと${変数}の表現が使える。あと、${変数}で、
+
などの演算子を使わずに、文字列をつなげることができるらしい。なので、let querystring = `?q=${query}
は、let querystring = '"?q=" + query
と同じはず。でも書いてみて思ったけどたしかに文字列をつなげるときは、${}
のほうが使いやすいそう(^^)このqiitaの記事がわかりやすかったです! http://qiita.com/kura07/items/c9fa858870ad56dfec12
はじめから、apiを使う仕様で作成したほうが楽そうだなぁ(^^)
Angular4 + Django1.11 vol.3
参考サイト
https://www.codingforentrepreneurs.com/projects/angular-django/ https://www.codingforentrepreneurs.com/blog/random-string-generator-in-python/ https://www.codingforentrepreneurs.com/blog/a-unique-slug-generator-for-django/
Videos Django App
- ng buildを起動した状態にしておく。
ng build --prod --output-path /Users/yassy/Desktop/djangular4/backend/src/static/ang/ --watch --output-hashing none
deploy.shに上記のコマンドを記載しておく。
現在の仕様では、video.service.tsが、videos.jsonからデータを取得しているが、これをdjangoのデータベースから直接持ってくるように設定したい。
まず、videos appを作成する。
$ python manage.py startapp videos
videos の modelを作成する。
from django.db import models # Create your models here. class Video(models.Model): name = models.CharField(max_length=220) slug = models.SlugField(unique=True, blank=True) embed = models.CharField(max_length=120, null=True, blank=True) featured = models.BooleanField(default=False) timestamp = models.DateTimeField(auto_now_add=True) def __str__(self): return self.name ''' "name": "Welcome", "slug": "item-1", "embed": "1hyjLD7pk10", "image": "/static/ang/assets/images/nature/4.jpg", "featured": true }, '''
Auto Generate Slug
- slugのauto generatorをutils.pyファイルに作る。以下のリンク参照 https://www.codingforentrepreneurs.com/blog/random-string-generator-in-python/ https://www.codingforentrepreneurs.com/blog/a-unique-slug-generator-for-django/
import random import string from django.utils.text import slugify def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits): return ''.join(random.choice(chars) for _ in range(size)) ''' random_string_generator is located here: http://joincfe.com/blog/random-string-generator-in-python/ ''' def unique_slug_generator(instance, new_slug=None): if new_slug is not None: slug = new_slug else: slug = slugify(instance.title) Klass = instance.__class__ qs_exists = Klass.objects.filter(slug=slug).exists() if qs_exists: new_slug = "{slug}-{randstr}".format( slug=slug, randstr=random_string_generator(size=4) ) return unique_slug_generator(instance, new_slug=new_slug) return slug ``` * 最終的にvideos/modelssは以下のように修正
from django.db import models from django.db.models.signals import pre_save
Create your models here.
from .utils import unique_slug_generator
class Video(models.Model): name = models.CharField(max_length=220) slug = models.SlugField(unique=True, blank=True) embed = models.CharField(max_length=120, help_text=‘Youtube Embed Code’, null=True, blank=True) featured = models.BooleanField(default=False) timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
def title(self):
return self.name
def video_pre_save_receiver(sender, instance, *args, **kwargs): if not instance.slug: instance.slug = unique_slug_generator(instance)
pre_save.connect(video_pre_save_receiver, sender=Video)
Angular4 + Django1.11 vol.2
参考サイト
https://www.codingforentrepreneurs.com/projects/angular-django/
ng build to Django Static
$ ng build --prod
で、production versionのbuildを実行する。(結果、bundle.jsが作成される)buildしたファイルの出力先をdjangoのstaciファイル内にする。
$ ng build --prod --output-path /Users/yassy/Desktop/djangular4/backend/src/static/ang --watch --output-hashing none // --output-path で出力先を指定 // --watchで、変更があったら自動でbuildするモードに切り替えられる // --output-hashing none で、build時に作成されるhashをなくすことができる。
- deploy.sh ファイルを作成する。deployのときに実行するコマンドを記載する。
ng build --prod --output-path /Users/yassy/Desktop/djangular4/backend/src/static/ang --watch --output-hashing none
Django render Angular
- static/ang/index.htmlをang_home.htmlにコピペする。さらに、load staticで、django templateで、staticfileを読み込むようにする。
{% load static %} <!doctype html> <html> <head> <meta charset="utf-8"> <title>Srvup</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <!-- index.html --> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <link href="{% static 'ang/styles.bundle.css' %}" rel="stylesheet"/></head> <body> <app-root>Loading...</app-root> <script type="text/javascript" src="{% static 'ang/inline.bundle.js' %}"></script> <script type="text/javascript" src="{% static 'ang/polyfills.bundle.js' %}"></script> <script type="text/javascript" src="{% static 'ang/vendor.bundle.js' %}"></script> <script type="text/javascript" src="{% static 'ang/main.bundle.js' %}"></script> </body> </html>
- 無事表示された!しかし、image ファイルなどが読み込まれていない。。。ang/assets/videos.jsonの中のpathがdjangoと一致してないのが原因ぽい。なので、そのimage のpathを修正する。
{ "name": "Welcome", "slug": "item-1", "embed": "1hyjLD7pk10", "image": "/static/ang/assets/images/nature/4.jpg", "featured": true } ...
- 次に、vides.service.ts内のendpoint(videos.jsonにアクセスするpath)も修正する。
const endpoint = '/static/ang/assets/json/videos.json'
http://127.0.0.1:8000/
にアクセスしてみる。。。error!というか画像が表示されない。。。原因は、videos.jsonをbuildあとのファイル(angフォルダ以下のファイル)を修正していたため、buildが実行されるたびに、上書きされていたためだった(^^; なので、client/assets/json/videos.jsonの方のpathを修正して再度buildする。無事表示された(^^)
home.component.tsの、defaultImageのpathも修正する。
videoListDefaultImage = '/static/ang/assets/images/videos/1.jpg'
まとめ
- angularアプリと、djangoアプリは別物と考える。
- angularアプリ作成→build→deployという流れだが、django backendに使うときは、angularアプリ作成→build output→outputしたファイルを、djangoに静的ファイルとして扱わせる という流れになるのか。
- build –watch にしておくことで、常にtranscompile + outputされる。そのため、基本的に、django側にoutputされたファイルを修正ではなく、angularアプリの方のファイルを修正する(djangoは、angularアプリからoutputされるファイルを扱うという役割)
Angular4 + Django1.11 vol.1
参考サイト
https://www.codingforentrepreneurs.com/projects/angular-django/
Getting Started Angular4+Django
djangular4というフォルダを作成する。さらに、djangular4/client, djangular4/backend というサイトをそれぞれ作成する。
clientフォルダに、joincfe/github のtry-angular-v4をgit cloneしてくる。
$ git clone https://github.com/codingforentrepreneurs/Try-Angular-v4.git . // ここのピリオドがポイント $ npm install // package.jsonに記載があるmoduleをinstallする。 $ ng serve // angularのコードをtranscompileして、localserverを起動する。 $ rm -rf .git // gitのrepositoryを削除する
- djangoの環境を作成する。
$ pyenv virtualenv djangular4 // 仮想環境を作成する $ pip install django djangorestframework // django djangorestframework をpip installする
A Django URL Catch-all
django startprojectで、新しいprojectを開始する。
$ django-admin.py startproject tryangular .
settings.pyにstaticfileの設定を追記する。
STATIC_URL = '/static/' STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'static-root') STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ]
- urls.pyにangularで表示するurlをcatchするための設定をする。
from django.conf.urls import url from django.contrib import admin from django.views.generic.base import TemplateView #template viewをimportする urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^.*', TemplateView.as_view(template_name="ang_home.html"), name='home'), # ]
- templatesフォルダを作成して、その中にang_home.htmlを作成する。
<h1>Hello Django!</h1>
- またsettings.pyにtemplatesのフォルダの場所を指定する。
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
http://127.0.0.1:8000/
でも、http://127.0.0.1:8000/ddd
でも、表示されるページが、ang_home.htmlになっていればOK。今後は、個別に表示したいurlがある場合は、(adminのように)、
r'^.*'
より上に書く。
まとめ
- これで一通りの準備は完了ぽい。
- .(ピリオド)を使うのがポイントだったな。
Angular4入門_Vol.20
参考サイト
https://www.codingforentrepreneurs.com/projects/try-angular-v4/
ngBuild and Deploy to Heroku
packageが完成したら、
$ ng build --prod
で、deploy用に、bundle.jsを作成する。prodオプションは、minファイルにするためか。bundle.jsには、typescriptファイルを役割ごとにまとめて、javascriptにtrans compileしたコードが記載されている。$ ng build --prod --output-path /Users/username/Desktop/try_angular4/ngSrvupTest
というコマンドでpathを指定して、ファイルを出力する。さらに、
$ ng build --prod --output-path /Users/username/Desktop/try_angular4/ngSrvupTest --watch
で、watchもできる。$ ng build --prod --output-path /Users/yassy/Desktop/try_angular4/ngSrvupTest/public/
というように、publicにしておいたほうがデプロイのときに楽ぽい。ngSrvupTest フォルダに、Procfileを作成する。
web: node index.js
- package.jsonを作成する(requirements.txtみたいなもんかな)
{ "name": "try-angular-4", "version": "1.0.0", "main": "index.js", "engines": { "node": "5.9.1" }, "dependencies": { "ejs": "2.4.1", "express": "4.13.3", "path": "0.12.7", "mongoose": "4.9.3", "body-parser": "1.17.1", "compression": "1.6.2" } }
- index.jsを作成する。
var express = require('express'); var path = require('path'); var app = express(); const port = process.env.PORT || '5000'; app.set('port', port); app.use(express.static(__dirname + '/public')); // staticファイルの置き場所? app.get('/[^\.]+$', function(req, res){ res.set('Content-Type', 'text/html') .sendFile(path.join(__dirname, '/public/index.html')) }); app.listen(app.get('port'), function(){ console.log("Node app is running at localhost:" + app.get('port')) });
$ node index.js
を実行してみる。。。error! express確認できないとのこと。$ npm install
で、package.jsonから必要なpackageをinstallする。$ node index.js
再度実行する。。。localhost:5000にアクセスしたところ無事表示された(^^).gitignore
ファイルを作成する。
node_modules .DS_Store
- herokuにデプロイするために、git repositoryをlocalに作成する。
$git init $git add --all $git commit -m "initial commit"
- herokuのrepositoryを作成する。
$ heroku create tryangular4 Creating ⬢ tryangular4yassy... done https://tryangular4.herokuapp.com/ | https://git.heroku.com/tryangular4.git
$ git push heroku master
で、deployする。。。デプロイ成功!上記で作成されたurlにアクセスすると、デプロイされているか確認できる(^^)