[{"data":1,"prerenderedAt":24077},["ShallowReactive",2],{"category-devstack-3":3},{"count":4,"content":5},43,[6,2441,3880,7960,12239,13461,16969,18607,20376,22399],{"id":7,"title":8,"body":9,"category":2426,"createdAt":2428,"description":2429,"extension":2430,"index":238,"meta":2431,"navigation":262,"path":2432,"publish":262,"seo":2433,"series":2434,"seriesTitle":2435,"stem":2436,"tag":2437,"thumbnail":2438,"updatedAt":2439,"__hash__":2440},"series\u002Fseries\u002Fvue-laravel-app-1.md","Vue SPA x Laravelでつくる実務パチモンアプリその１：アプリの概要と環境構築",{"type":10,"value":11,"toc":2402},"minimark",[12,16,35,47,50,70,73,77,80,84,87,91,122,125,162,165,176,179,182,187,190,193,204,218,225,304,318,323,327,330,384,387,390,393,411,469,476,480,483,842,859,868,926,929,937,951,960,966,981,984,987,991,998,1004,1007,1011,1014,1018,1024,1047,1053,1185,1196,1199,1224,1231,1237,1241,1248,1254,1257,1318,1321,1460,1467,1470,1595,1678,1681,2016,2023,2030,2033,2052,2227,2236,2248,2285,2288,2327,2333,2346,2357,2360,2373,2376,2385,2388,2391,2395,2398],[13,14,15],"p",{},"こんにちはjunです。仕事で中規模プロジェクトのディレクターとしてアサインされて、半年ほどブログを書けませんでした。ようやく最近時間が出てきたので新しいシリーズ記事を作成しようと思いました。とにかく最近１年はシステムばっかり作っていました。それぞのれプロジェクトでは",[17,18,19,23,26,29,32],"ul",{},[20,21,22],"li",{},"CRUDなAPI",[20,24,25],{},"管理画面の構築",[20,27,28],{},"ユーザー権限によるアクセス制限",[20,30,31],{},"ログイン・ログアウト",[20,33,34],{},"ジョブ・キューを用いた長い処理",[13,36,37,38,42,43,46],{},"など使用するシステムの構築を多く行い、いろいろ学ぶことできました。その中で「CRUDなAPI」を考えた「管理画面」の構築をすることが多くありました。バックエンドは",[39,40,41],"code",{},"Laravel","を、フロントエンドは",[39,44,45],{},"Vue.js","を使用していました。Vue.jsのおかげで高速にリッチなUIを構築し、システムを開発することができました。",[13,48,49],{},"この知見を共有し、まとめるためにも今回は",[17,51,52,55,58,61,64,67],{},[20,53,54],{},"管理画面はVue.js SPA",[20,56,57],{},"web APIによるCRUD操作",[20,59,60],{},"ルーティング設計",[20,62,63],{},"バリデーション",[20,65,66],{},"MVCによるアプリケーション設計",[20,68,69],{},"laravel\u002Fpermissionを用いたユーザー権限",[13,71,72],{},"以上の様な機能を持ったデモアプリを作ろうと思います。Laravelを用いたシステム開発と、Vue.jsによる管理画面フロントエンド開発を解説していきます。",[74,75,76],"h2",{"id":76},"作るアプリの概要",[13,78,79],{},"今回のアプリはn○teみたいなブログサービスを作ります。CRUDや管理画面の構築をメインに行いたいのでシンプルにいきます。",[81,82,83],"h3",{"id":83},"機能概要",[13,85,86],{},"ざっくりとした機能概要は以下のとおりです。",[88,89,90],"h4",{"id":90},"ユーザー系の特徴",[17,92,93,96,99,102,105,108],{},[20,94,95],{},"利用する際にはユーザーとしてアカウントを作る（今回は全てゲストとする）。",[20,97,98],{},"ログインはアドレスとパスワードを使用する。",[20,100,101],{},"アプリを利用する一般ユーザーと管理を行う管理ユーザーが存在する。",[20,103,104],{},"管理ユーザーは特定の管理用ルートから入る。",[20,106,107],{},"退会可能。退会時は関連するデータは削除される。",[20,109,110,111],{},"プロフィールでは以下の項目を持つ\n",[17,112,113,116,119],{},[20,114,115],{},"ユーザー名（仮名）",[20,117,118],{},"プロフィール文",[20,120,121],{},"アバター写真",[88,123,124],{"id":124},"ブログ機能",[17,126,127,130,147,150,153,156,159],{},[20,128,129],{},"ブログを作成することができ、公開することができる。",[20,131,132,133],{},"ブログは以下の項目を持つ\n",[17,134,135,138,141,144],{},[20,136,137],{},"タイトル",[20,139,140],{},"内容（リッチテキスト）",[20,142,143],{},"タグ（任意）",[20,145,146],{},"公開日時",[20,148,149],{},"下書きとして保存することができる。更新時も下書き可能。",[20,151,152],{},"任意数のタグを添付できる。タグはユーザーが新しく作成できる。",[20,154,155],{},"削除可能",[20,157,158],{},"画像の添付が可能。",[20,160,161],{},"アップロードした画像は管理できる。",[88,163,164],{"id":164},"一覧検索機能",[17,166,167,170,173],{},[20,168,169],{},"サイトトップは投稿された記事が新着順に並ぶ。",[20,171,172],{},"任意のタグを選んで一覧表示することが可能。",[20,174,175],{},"部分一致検索も一応可能とする。",[81,177,178],{"id":178},"アプリケーションアーキテクチャー",[13,180,181],{},"バックエンドにはLaravel9、管理画面はVue.js(2系)を使用して構築します。なおVue.jsはSPA構成とします。記事の一覧や詳細画面などの公開側はLaravelのレンダリングで表示します。",[183,184],"image-render",{":src":185,":center":186},"'vue_laravel_app\u002Farchitecture.jpg'","true",[13,188,189],{},"デザインに関してはセンスが皆無なので管理画面・公開側ともにBootstrapを使用します。",[74,191,192],{"id":192},"環境構築",[13,194,195,196,203],{},"ではまずは環境構築を行っていきましょう。環境構築にはDockerを使用してLAMP環境を作ります。",[197,198,202],"a",{"href":199,"rel":200},"https:\u002F\u002Fwww.twilio.com\u002Fblog\u002Fget-started-docker-laravel-jp",[201],"nofollow","こちらの記事","を参考にし、",[17,205,206,209,212,215],{},[20,207,208],{},"mysql5.7",[20,210,211],{},"phpmyadmin",[20,213,214],{},"apache2.4",[20,216,217],{},"php8.1",[13,219,220,221,224],{},"以上の構成を作成したいと思います。ディレクトリを作成して",[39,222,223],{},"docker-compose.yaml","を作成します。",[226,227,232],"pre",{"className":228,"code":229,"language":230,"meta":231,"style":231},"language-bash shiki shiki-themes material-theme-ocean","mkdir ~\u002Flaravel_vue\ncd  ~\u002Flaravel_vue\n\ntouch docker-compose.yaml\nmkdir html\nmkdir web_1\ncd web_1\ntouch Dockerfile\n","bash","",[39,233,234,247,257,264,273,281,289,296],{"__ignoreMap":231},[235,236,239,243],"span",{"class":237,"line":238},"line",1,[235,240,242],{"class":241},"s5Dmg","mkdir",[235,244,246],{"class":245},"sfyAc"," ~\u002Flaravel_vue\n",[235,248,250,254],{"class":237,"line":249},2,[235,251,253],{"class":252},"sdLwU","cd",[235,255,256],{"class":245},"  ~\u002Flaravel_vue\n",[235,258,260],{"class":237,"line":259},3,[235,261,263],{"emptyLinePlaceholder":262},true,"\n",[235,265,267,270],{"class":237,"line":266},4,[235,268,269],{"class":241},"touch",[235,271,272],{"class":245}," docker-compose.yaml\n",[235,274,276,278],{"class":237,"line":275},5,[235,277,242],{"class":241},[235,279,280],{"class":245}," html\n",[235,282,284,286],{"class":237,"line":283},6,[235,285,242],{"class":241},[235,287,288],{"class":245}," web_1\n",[235,290,292,294],{"class":237,"line":291},7,[235,293,253],{"class":252},[235,295,288],{"class":245},[235,297,299,301],{"class":237,"line":298},8,[235,300,269],{"class":241},[235,302,303],{"class":245}," Dockerfile\n",[13,305,306,309,310,313,314,317],{},[39,307,308],{},"html\u002F","という名前で作成したディレクトリにLaravelのソースが作成され、Dockerコンテナにマウントされる様にします。",[39,311,312],{},"web_1\u002F","ディレクトリにはphpとapacheが構築できる",[39,315,316],{},"Dockerfile","を作成してビルドします。",[13,319,320,322],{},[39,321,223],{},"でDBとapache+phpと連結したいと思います。",[81,324,326],{"id":325},"dockerfile設定","Dockerfile設定",[13,328,329],{},"まずはapacheとphpのイメージをDockerfileを作成します。",[226,331,336],{"className":332,"code":333,"filename":334,"language":335,"meta":231,"style":231},"language-dockerfie shiki shiki-themes material-theme-ocean","FROM php:8.1-apache\nRUN apt update \\\n        && apt install -y g++ libicu-dev libpq-dev libzip-dev zip zlib1g-dev \\\n        && mv \u002Fetc\u002Fapache2\u002Fmods-available\u002Frewrite.load \u002Fetc\u002Fapache2\u002Fmods-enabled\nRUN docker-php-ext-install pdo pdo_mysql\nWORKDIR \u002Fvar\u002Fwww\u002Fhtml\nRUN curl -sS https:\u002F\u002Fgetcomposer.org\u002Finstaller | php -- --install-dir=\u002Fusr\u002Flocal\u002Fbin --filename=composer\nRUN curl -fsSL https:\u002F\u002Fdeb.nodesource.com\u002Fsetup_lts.x | bash - \\\n    && apt-get install -y nodejs\n","web_1\u002FDockerfile","dockerfie",[39,337,338,343,348,353,358,363,368,373,378],{"__ignoreMap":231},[235,339,340],{"class":237,"line":238},[235,341,342],{},"FROM php:8.1-apache\n",[235,344,345],{"class":237,"line":249},[235,346,347],{},"RUN apt update \\\n",[235,349,350],{"class":237,"line":259},[235,351,352],{},"        && apt install -y g++ libicu-dev libpq-dev libzip-dev zip zlib1g-dev \\\n",[235,354,355],{"class":237,"line":266},[235,356,357],{},"        && mv \u002Fetc\u002Fapache2\u002Fmods-available\u002Frewrite.load \u002Fetc\u002Fapache2\u002Fmods-enabled\n",[235,359,360],{"class":237,"line":275},[235,361,362],{},"RUN docker-php-ext-install pdo pdo_mysql\n",[235,364,365],{"class":237,"line":283},[235,366,367],{},"WORKDIR \u002Fvar\u002Fwww\u002Fhtml\n",[235,369,370],{"class":237,"line":291},[235,371,372],{},"RUN curl -sS https:\u002F\u002Fgetcomposer.org\u002Finstaller | php -- --install-dir=\u002Fusr\u002Flocal\u002Fbin --filename=composer\n",[235,374,375],{"class":237,"line":298},[235,376,377],{},"RUN curl -fsSL https:\u002F\u002Fdeb.nodesource.com\u002Fsetup_lts.x | bash - \\\n",[235,379,381],{"class":237,"line":380},9,[235,382,383],{},"    && apt-get install -y nodejs\n",[13,385,386],{},"このファイルではphpとapacheが入った環境にてLaravelの依存PHPモジュールのインストールとcomposerをインストールする内容を記述しています。そしてLaravelのアセットビルドにはnode.jsを使用するのでそのインストールも記述しています。",[81,388,389],{"id":389},"apacheの設定ファイルを作成",[13,391,392],{},"Laravelのドキュメントルートを設定するためにapacheの設定ファイル作成して、マウントできる様にします。",[226,394,396],{"className":228,"code":395,"language":230,"meta":231,"style":231},"cd web_1\ntouch default.conf\n",[39,397,398,404],{"__ignoreMap":231},[235,399,400,402],{"class":237,"line":238},[235,401,253],{"class":252},[235,403,288],{"class":245},[235,405,406,408],{"class":237,"line":249},[235,407,269],{"class":241},[235,409,410],{"class":245}," default.conf\n",[226,412,417],{"className":413,"code":414,"filename":415,"language":416,"meta":231,"style":231},"language-conf shiki shiki-themes material-theme-ocean","\u003CVirtualHost *:80>\n    ServerName laravel_docker\n    DocumentRoot \u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\n\n    \u003CDirectory \"\u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\">\n        AllowOverride All\n    \u003C\u002FDirectory>\n    ErrorLog ${APACHE_LOG_DIR}\u002Ferror.log\n    CustomLog ${APACHE_LOG_DIR}\u002Faccess.log combined\n\u003C\u002FVirtualHost>\n","default.conf","conf",[39,418,419,424,429,434,438,443,448,453,458,463],{"__ignoreMap":231},[235,420,421],{"class":237,"line":238},[235,422,423],{},"\u003CVirtualHost *:80>\n",[235,425,426],{"class":237,"line":249},[235,427,428],{},"    ServerName laravel_docker\n",[235,430,431],{"class":237,"line":259},[235,432,433],{},"    DocumentRoot \u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\n",[235,435,436],{"class":237,"line":266},[235,437,263],{"emptyLinePlaceholder":262},[235,439,440],{"class":237,"line":275},[235,441,442],{},"    \u003CDirectory \"\u002Fvar\u002Fwww\u002Fhtml\u002Fpublic\">\n",[235,444,445],{"class":237,"line":283},[235,446,447],{},"        AllowOverride All\n",[235,449,450],{"class":237,"line":291},[235,451,452],{},"    \u003C\u002FDirectory>\n",[235,454,455],{"class":237,"line":298},[235,456,457],{},"    ErrorLog ${APACHE_LOG_DIR}\u002Ferror.log\n",[235,459,460],{"class":237,"line":380},[235,461,462],{},"    CustomLog ${APACHE_LOG_DIR}\u002Faccess.log combined\n",[235,464,466],{"class":237,"line":465},10,[235,467,468],{},"\u003C\u002FVirtualHost>\n",[13,470,471,472,475],{},"このファイルはコンテナの",[39,473,474],{},"\u002Fetc\u002Fapache2\u002Fsites-enabled\u002F000-default.conf","にマウントされます。",[81,477,479],{"id":478},"docker-composeyamlを作成","docker-compose.yamlを作成",[13,481,482],{},"次にdocker-comose.yamlを作成してDBとphpmyadmin",[226,484,489],{"className":485,"code":486,"filename":487,"language":488,"meta":231,"style":231},"language-yaml shiki shiki-themes material-theme-ocean","version: '3'\nservices: \n  web_1:\n    build: .\u002Fweb_1\n    depends_on: \n      - db\n    volumes: \n      - .\u002Fhtml\u002F:\u002Fvar\u002Fwww\u002Fhtml\u002F\n      - .\u002Fweb_1\u002Fdefault.conf:\u002Fetc\u002Fapache2\u002Fsites-enabled\u002F000-default.conf\n    ports: \n      - \"8005:80\"\n  phpmyadmin:\n    image: phpmyadmin\n    restart: always\n    ports:\n      - \"8080:80\"\n    environment:\n     - PMA_ARBITRARY=1\n     - PMA_HOST=db:3306\n     - PMA_USER=root\n     - PMA_PASSWORD=rootroot\n  db:\n    image: mysql:5.7\n    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci\n    environment:\n      MYSQL_DATABASE: preform\n      MYSQL_USER: test\n      MYSQL_PASSWORD: testtest\n      MYSQL_ROOT_PASSWORD: rootroot\n      TZ: Asia\u002FTokyo\n    ports: \n      - \"3306:3306\"\n    volumes: \n      - vue_laravel:\u002Fvar\u002Flib\u002Fmysql\nvolumes: \n  vue_laravel: {}\n","docker-comose.yaml","yaml",[39,490,491,510,521,529,539,548,556,565,572,579,588,602,610,621,632,639,651,659,668,676,684,692,700,710,721,728,739,750,761,772,783,792,804,813,821,831],{"__ignoreMap":231},[235,492,493,497,501,504,507],{"class":237,"line":238},[235,494,496],{"class":495},"s-wAU","version",[235,498,500],{"class":499},"sAklC",":",[235,502,503],{"class":499}," '",[235,505,506],{"class":245},"3",[235,508,509],{"class":499},"'\n",[235,511,512,515,517],{"class":237,"line":249},[235,513,514],{"class":495},"services",[235,516,500],{"class":499},[235,518,520],{"class":519},"s0W1g"," \n",[235,522,523,526],{"class":237,"line":259},[235,524,525],{"class":495},"  web_1",[235,527,528],{"class":499},":\n",[235,530,531,534,536],{"class":237,"line":266},[235,532,533],{"class":495},"    build",[235,535,500],{"class":499},[235,537,538],{"class":245}," .\u002Fweb_1\n",[235,540,541,544,546],{"class":237,"line":275},[235,542,543],{"class":495},"    depends_on",[235,545,500],{"class":499},[235,547,520],{"class":519},[235,549,550,553],{"class":237,"line":283},[235,551,552],{"class":499},"      -",[235,554,555],{"class":245}," db\n",[235,557,558,561,563],{"class":237,"line":291},[235,559,560],{"class":495},"    volumes",[235,562,500],{"class":499},[235,564,520],{"class":519},[235,566,567,569],{"class":237,"line":298},[235,568,552],{"class":499},[235,570,571],{"class":245}," .\u002Fhtml\u002F:\u002Fvar\u002Fwww\u002Fhtml\u002F\n",[235,573,574,576],{"class":237,"line":380},[235,575,552],{"class":499},[235,577,578],{"class":245}," .\u002Fweb_1\u002Fdefault.conf:\u002Fetc\u002Fapache2\u002Fsites-enabled\u002F000-default.conf\n",[235,580,581,584,586],{"class":237,"line":465},[235,582,583],{"class":495},"    ports",[235,585,500],{"class":499},[235,587,520],{"class":519},[235,589,591,593,596,599],{"class":237,"line":590},11,[235,592,552],{"class":499},[235,594,595],{"class":499}," \"",[235,597,598],{"class":245},"8005:80",[235,600,601],{"class":499},"\"\n",[235,603,605,608],{"class":237,"line":604},12,[235,606,607],{"class":495},"  phpmyadmin",[235,609,528],{"class":499},[235,611,613,616,618],{"class":237,"line":612},13,[235,614,615],{"class":495},"    image",[235,617,500],{"class":499},[235,619,620],{"class":245}," phpmyadmin\n",[235,622,624,627,629],{"class":237,"line":623},14,[235,625,626],{"class":495},"    restart",[235,628,500],{"class":499},[235,630,631],{"class":245}," always\n",[235,633,635,637],{"class":237,"line":634},15,[235,636,583],{"class":495},[235,638,528],{"class":499},[235,640,642,644,646,649],{"class":237,"line":641},16,[235,643,552],{"class":499},[235,645,595],{"class":499},[235,647,648],{"class":245},"8080:80",[235,650,601],{"class":499},[235,652,654,657],{"class":237,"line":653},17,[235,655,656],{"class":495},"    environment",[235,658,528],{"class":499},[235,660,662,665],{"class":237,"line":661},18,[235,663,664],{"class":499},"     -",[235,666,667],{"class":245}," PMA_ARBITRARY=1\n",[235,669,671,673],{"class":237,"line":670},19,[235,672,664],{"class":499},[235,674,675],{"class":245}," PMA_HOST=db:3306\n",[235,677,679,681],{"class":237,"line":678},20,[235,680,664],{"class":499},[235,682,683],{"class":245}," PMA_USER=root\n",[235,685,687,689],{"class":237,"line":686},21,[235,688,664],{"class":499},[235,690,691],{"class":245}," PMA_PASSWORD=rootroot\n",[235,693,695,698],{"class":237,"line":694},22,[235,696,697],{"class":495},"  db",[235,699,528],{"class":499},[235,701,703,705,707],{"class":237,"line":702},23,[235,704,615],{"class":495},[235,706,500],{"class":499},[235,708,709],{"class":245}," mysql:5.7\n",[235,711,713,716,718],{"class":237,"line":712},24,[235,714,715],{"class":495},"    command",[235,717,500],{"class":499},[235,719,720],{"class":245}," mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci\n",[235,722,724,726],{"class":237,"line":723},25,[235,725,656],{"class":495},[235,727,528],{"class":499},[235,729,731,734,736],{"class":237,"line":730},26,[235,732,733],{"class":495},"      MYSQL_DATABASE",[235,735,500],{"class":499},[235,737,738],{"class":245}," preform\n",[235,740,742,745,747],{"class":237,"line":741},27,[235,743,744],{"class":495},"      MYSQL_USER",[235,746,500],{"class":499},[235,748,749],{"class":245}," test\n",[235,751,753,756,758],{"class":237,"line":752},28,[235,754,755],{"class":495},"      MYSQL_PASSWORD",[235,757,500],{"class":499},[235,759,760],{"class":245}," testtest\n",[235,762,764,767,769],{"class":237,"line":763},29,[235,765,766],{"class":495},"      MYSQL_ROOT_PASSWORD",[235,768,500],{"class":499},[235,770,771],{"class":245}," rootroot\n",[235,773,775,778,780],{"class":237,"line":774},30,[235,776,777],{"class":495},"      TZ",[235,779,500],{"class":499},[235,781,782],{"class":245}," Asia\u002FTokyo\n",[235,784,786,788,790],{"class":237,"line":785},31,[235,787,583],{"class":495},[235,789,500],{"class":499},[235,791,520],{"class":519},[235,793,795,797,799,802],{"class":237,"line":794},32,[235,796,552],{"class":499},[235,798,595],{"class":499},[235,800,801],{"class":245},"3306:3306",[235,803,601],{"class":499},[235,805,807,809,811],{"class":237,"line":806},33,[235,808,560],{"class":495},[235,810,500],{"class":499},[235,812,520],{"class":519},[235,814,816,818],{"class":237,"line":815},34,[235,817,552],{"class":499},[235,819,820],{"class":245}," vue_laravel:\u002Fvar\u002Flib\u002Fmysql\n",[235,822,824,827,829],{"class":237,"line":823},35,[235,825,826],{"class":495},"volumes",[235,828,500],{"class":499},[235,830,520],{"class":519},[235,832,834,837,839],{"class":237,"line":833},36,[235,835,836],{"class":495},"  vue_laravel",[235,838,500],{"class":499},[235,840,841],{"class":499}," {}\n",[13,843,844,847,848,850,851,854,855,858],{},[39,845,846],{},"web_1","サービスでapacheとphpの環境をビルドします。そして",[39,849,308],{},"をコンテナ内の",[39,852,853],{},"\u002Fvar\u002Fwww\u002Fhtml\u002F","にマウントされます。ubuntuのapacheは",[39,856,857],{},"\u002Fetc\u002Fapache2\u002Fsites-enabled\u002F","配下にconfファイルを設置することで設定を追加したりオーバーライドできます。",[13,860,861,863,864,867],{},[39,862,211],{},"サービスでphpmyadminを起動してDBの内容を編集しやすくします。",[39,865,866],{},"db","サービスではmysqlの環境を作成します。ボリュームの設定をして永続化を行います。以上の設定を行ったらコンテナを立ち上げます。",[226,869,871],{"className":228,"code":870,"language":230,"meta":231,"style":231},"docker-compose up -d\n\nCreating laravel_vue_phpmyadmin_1 ... done\nCreating laravel_vue_db_1         ... done\nCreating laravel_vue_web_1_1      ... done\n",[39,872,873,884,888,902,914],{"__ignoreMap":231},[235,874,875,878,881],{"class":237,"line":238},[235,876,877],{"class":241},"docker-compose",[235,879,880],{"class":245}," up",[235,882,883],{"class":245}," -d\n",[235,885,886],{"class":237,"line":249},[235,887,263],{"emptyLinePlaceholder":262},[235,889,890,893,896,899],{"class":237,"line":259},[235,891,892],{"class":241},"Creating",[235,894,895],{"class":245}," laravel_vue_phpmyadmin_1",[235,897,898],{"class":245}," ...",[235,900,901],{"class":245}," done\n",[235,903,904,906,909,912],{"class":237,"line":266},[235,905,892],{"class":241},[235,907,908],{"class":245}," laravel_vue_db_1",[235,910,911],{"class":245},"         ...",[235,913,901],{"class":245},[235,915,916,918,921,924],{"class":237,"line":275},[235,917,892],{"class":241},[235,919,920],{"class":245}," laravel_vue_web_1_1",[235,922,923],{"class":245},"      ...",[235,925,901],{"class":245},[13,927,928],{},"そしてコンテナ内に入ってLaravelをインストールしていきます。",[226,930,935],{"className":931,"code":933,"language":934},[932],"language-text","docker exec -it laravel_vue_web_1_1 \u002Fbin\u002Fbash\n\nroot@a790844c74d6:\u002Fvar\u002Fwww\u002Fhtml# composer \nroot@a790844c74d6:\u002Fvar\u002Fwww\u002Fhtml# composer create-project laravel\u002Flaravel .\u002F\n","text",[39,936,933],{"__ignoreMap":231},[13,938,939,940,943,944,947,948,950],{},"これで",[39,941,942],{},"\u002Fvar\u002Fwww\u002Fhtml","配下にLaravelプロジェクトが入ります。コンテナの",[39,945,946],{}," \u002Fvar\u002Fwww\u002Fhtml","はホストマシンの",[39,949,308],{},"に同期されます。",[13,952,953,955,956,959],{},[39,954,308],{},"配下にソースが生成されたのを確認しましたら、",[39,957,958],{},".env","ファイルにDBの接続設定を記述します。",[226,961,964],{"className":962,"code":963,"filename":958,"language":934,"meta":231},[932],"DB_CONNECTION=mysql\nDB_HOST=db\nDB_PORT=3306\nDB_DATABASE=laravel\nDB_USERNAME=root\nDB_PASSWORD=rootroot\n",[39,965,963],{"__ignoreMap":231},[13,967,968,969,972,973,976,977,980],{},"phpmyadminとかで",[39,970,971],{},"laravel","データベースは作成しておいてください。",[39,974,975],{},"DB_HOST","はdockerのDBのサービス名を入力します。設定したらブラウザで",[39,978,979],{},"localhost:8005","にアクセスします。以下の様なウェルカムページが表示されれば成功です。",[183,982],{":src":983,":center":186},"'vue_laravel_app\u002Flaravel_welcome.png'",[13,985,986],{},"（特に断りがない限り、以降ではDockerコンテナ内の操作とします。）",[74,988,990],{"id":989},"laravelとvueセットアップ","LaravelとVueセットアップ",[13,992,993,994,997],{},"それではアセットと認証機能のセットアップをしましょう。今回は",[39,995,996],{},"laravel\u002Fbreeze","をスターターキットとして利用します。",[226,999,1002],{"className":1000,"code":1001,"language":934},[932],"composer require laravel\u002Fbreeze --dev\n\nphp artisan breeze:install\nBreeze scaffolding installed successfully.\nPlease execute the \"npm install && npm run dev\" command to build your assets.\n\nnpm install\nnpm run dev\nphp artisan migrate\nMigration table created successfully.\nMigrating: 2014_10_12_000000_create_users_table\nMigrated:  2014_10_12_000000_create_users_table (23.69ms)\nMigrating: 2014_10_12_100000_create_password_resets_table\nMigrated:  2014_10_12_100000_create_password_resets_table (10.45ms)\nMigrating: 2019_08_19_000000_create_failed_jobs_table\nMigrated:  2019_08_19_000000_create_failed_jobs_table (10.60ms)\nMigrating: 2019_12_14_000001_create_personal_access_tokens_table\nMigrated:  2019_12_14_000001_create_personal_access_tokens_table (14.54ms)\n",[39,1003,1001],{"__ignoreMap":231},[13,1005,1006],{},"マイグレーションが完了したので登録などができる様になっているはずです。ひとまずLaravelのセットアップは以上となります。",[74,1008,1010],{"id":1009},"とりあえずspa構成ができるかチェック","とりあえずSPA構成ができるかチェック",[13,1012,1013],{},"次は管理画面のフロントエンドのセットアップをしていきます。管理画面はvue.jsで作成し、公開側コンテンツはLaravelのサーバーサイドレンダリングをします。ここではSPA構成のセットアップをします。",[81,1015,1017],{"id":1016},"spaのビューとルートの設定","SPAのビューとルートの設定",[13,1019,1020,1023],{},[39,1021,1022],{},"\u002Fsystem","配下を管理画面として構築していきます。以下の様なビューテンプレートとルートを作成します。",[226,1025,1030],{"className":1026,"code":1027,"filename":1028,"language":1029,"meta":231,"style":231},"language-php shiki shiki-themes material-theme-ocean","Route::get('\u002Fsystem\u002F{path?}', function () {\n    return view('admin');\n})->where('path', '.*')->name('admin');\n","routes\u002Fweb.php","php",[39,1031,1032,1037,1042],{"__ignoreMap":231},[235,1033,1034],{"class":237,"line":238},[235,1035,1036],{},"Route::get('\u002Fsystem\u002F{path?}', function () {\n",[235,1038,1039],{"class":237,"line":249},[235,1040,1041],{},"    return view('admin');\n",[235,1043,1044],{"class":237,"line":259},[235,1045,1046],{},"})->where('path', '.*')->name('admin');\n",[13,1048,1049,1050,1052],{},"このルートは",[39,1051,1022],{},"配下すべてのルートに対してadminビューを返すことを示しています。",[226,1054,1057],{"className":1026,"code":1055,"filename":1056,"language":1029,"meta":231,"style":231},"\u003C!DOCTYPE html>\n\u003Chtml lang=\"{{ str_replace('_', '-', app()->getLocale()) }}\">\n    \u003Chead>\n        \u003Cmeta charset=\"utf-8\">\n        \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n        \u003Cmeta name=\"csrf-token\" content=\"{{ csrf_token() }}\">\n\n        \u003Ctitle>{{ config('app.name', 'Laravel') }}\u003C\u002Ftitle>\n\n        \u003C!-- Fonts -->\n        \u003Clink rel=\"stylesheet\" href=\"https:\u002F\u002Ffonts.googleapis.com\u002Fcss2?family=Nunito:wght@400;600;700&display=swap\">\n\n        \u003C!-- Styles -->\n        \u003Clink rel=\"stylesheet\" href=\"{{ asset('css\u002Fapp.css') }}\">\n\n    \u003C\u002Fhead>\n    \u003Cbody>\n        \u003Cdiv class=\"font-sans text-gray-900 antialiased\">\n            \u003Cdiv id=\"app\">\n                \u003Crouter-view\u002F>\n            \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n    \u003C\u002Fbody>\n    \u003C!-- Scripts -->\n    \u003Cscript src=\"{{ asset('js\u002Fadmin\u002Findex.js') }}\" defer>\u003C\u002Fscript>\n\u003C\u002Fhtml>\n","resources\u002Fview\u002Fadmin.blade.php",[39,1058,1059,1064,1069,1074,1079,1084,1089,1093,1098,1102,1107,1112,1116,1121,1126,1130,1135,1140,1145,1150,1155,1160,1165,1170,1175,1180],{"__ignoreMap":231},[235,1060,1061],{"class":237,"line":238},[235,1062,1063],{},"\u003C!DOCTYPE html>\n",[235,1065,1066],{"class":237,"line":249},[235,1067,1068],{},"\u003Chtml lang=\"{{ str_replace('_', '-', app()->getLocale()) }}\">\n",[235,1070,1071],{"class":237,"line":259},[235,1072,1073],{},"    \u003Chead>\n",[235,1075,1076],{"class":237,"line":266},[235,1077,1078],{},"        \u003Cmeta charset=\"utf-8\">\n",[235,1080,1081],{"class":237,"line":275},[235,1082,1083],{},"        \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n",[235,1085,1086],{"class":237,"line":283},[235,1087,1088],{},"        \u003Cmeta name=\"csrf-token\" content=\"{{ csrf_token() }}\">\n",[235,1090,1091],{"class":237,"line":291},[235,1092,263],{"emptyLinePlaceholder":262},[235,1094,1095],{"class":237,"line":298},[235,1096,1097],{},"        \u003Ctitle>{{ config('app.name', 'Laravel') }}\u003C\u002Ftitle>\n",[235,1099,1100],{"class":237,"line":380},[235,1101,263],{"emptyLinePlaceholder":262},[235,1103,1104],{"class":237,"line":465},[235,1105,1106],{},"        \u003C!-- Fonts -->\n",[235,1108,1109],{"class":237,"line":590},[235,1110,1111],{},"        \u003Clink rel=\"stylesheet\" href=\"https:\u002F\u002Ffonts.googleapis.com\u002Fcss2?family=Nunito:wght@400;600;700&display=swap\">\n",[235,1113,1114],{"class":237,"line":604},[235,1115,263],{"emptyLinePlaceholder":262},[235,1117,1118],{"class":237,"line":612},[235,1119,1120],{},"        \u003C!-- Styles -->\n",[235,1122,1123],{"class":237,"line":623},[235,1124,1125],{},"        \u003Clink rel=\"stylesheet\" href=\"{{ asset('css\u002Fapp.css') }}\">\n",[235,1127,1128],{"class":237,"line":634},[235,1129,263],{"emptyLinePlaceholder":262},[235,1131,1132],{"class":237,"line":641},[235,1133,1134],{},"    \u003C\u002Fhead>\n",[235,1136,1137],{"class":237,"line":653},[235,1138,1139],{},"    \u003Cbody>\n",[235,1141,1142],{"class":237,"line":661},[235,1143,1144],{},"        \u003Cdiv class=\"font-sans text-gray-900 antialiased\">\n",[235,1146,1147],{"class":237,"line":670},[235,1148,1149],{},"            \u003Cdiv id=\"app\">\n",[235,1151,1152],{"class":237,"line":678},[235,1153,1154],{},"                \u003Crouter-view\u002F>\n",[235,1156,1157],{"class":237,"line":686},[235,1158,1159],{},"            \u003C\u002Fdiv>\n",[235,1161,1162],{"class":237,"line":694},[235,1163,1164],{},"        \u003C\u002Fdiv>\n",[235,1166,1167],{"class":237,"line":702},[235,1168,1169],{},"    \u003C\u002Fbody>\n",[235,1171,1172],{"class":237,"line":712},[235,1173,1174],{},"    \u003C!-- Scripts -->\n",[235,1176,1177],{"class":237,"line":723},[235,1178,1179],{},"    \u003Cscript src=\"{{ asset('js\u002Fadmin\u002Findex.js') }}\" defer>\u003C\u002Fscript>\n",[235,1181,1182],{"class":237,"line":730},[235,1183,1184],{},"\u003C\u002Fhtml>\n",[13,1186,1187,1188,1191,1192,1195],{},"テンプレートは上記の様にして",[39,1189,1190],{},"\u003Cdiv id=\"app\">\u003Crouter-view\u002F>\u003C\u002Fdiv>","を設置して、vueのエントリーポイントと、vueのビルドファイルを読み込む様にします。実際はヘッダーなどを分けたほうがいいですが、今はとりあえずこんな感じでOKです。\n次に",[39,1193,1194],{},"'js\u002Fadmin\u002Findex.js","で読み込ませるjsファイルを作成していきます。",[81,1197,1198],{"id":1198},"必要なライブラリをインストール",[13,1200,1201,1202,1205,1206,1209,1210,1213,1214,1216,1217,1209,1220,1223],{},"一昔前の",[39,1203,1204],{},"laravel\u002Fui","の時は",[39,1207,1208],{},"vue","と",[39,1211,1212],{},"bootstrap","の設定がインストール時に自動設定されますが、今回の",[39,1215,996],{},"は",[39,1218,1219],{},"alpinejs",[39,1221,1222],{},"tailwindcss","が入っているので、vue一式を自分でインストールする必要があります。まずはVue・Vuex・Vue-Routerをインストールしましょう。",[1225,1226,1230],"div",{"className":1227},[1228,1229],"alert","alert-danger","\nこの記事を作成した2021年3月現在、Vue3がリリースされておりバージョンを指定しないと、それぞれ最新版がインストールされる可能性があります。この記事はVue2を用いて解説しますのでバージョンを指定してインストールしています。\n",[226,1232,1235],{"className":1233,"code":1234,"language":934},[932],"npm install vue@2 vue-loader@15 vue-template-compiler@2 --save-dev\nnpm install vuex@3 vue-router@3\n",[39,1236,1234],{"__ignoreMap":231},[81,1238,1240],{"id":1239},"spa用のjsファイルを作成する","SPA用のJSファイルを作成する",[13,1242,1243,1244,1247],{},"それでは",[39,1245,1246],{},"resources\u002Fjs","配下にSPAのファイルを作成を行います。以下の様にファイルとディレクトリを作成してください。",[226,1249,1252],{"className":1250,"code":1251,"language":934},[932],"js\n├── admin\n│   ├── index.js\n│   ├── router.js\n│   └── store.js\n└── vue\n    └── page\n        ├── Home.vue\n        └── Profile.vue\n",[39,1253,1251],{"__ignoreMap":231},[13,1255,1256],{},"store.jsとrouter.jsは以下の様にします。",[226,1258,1263],{"className":1259,"code":1260,"filename":1261,"language":1262,"meta":231,"style":231},"language-js shiki shiki-themes material-theme-ocean","export default {\n    state:{},\n    getters: {},\n    mutations: {},\n    actions: {}\n}\n","store.js","js",[39,1264,1265,1277,1285,1295,1304,1313],{"__ignoreMap":231},[235,1266,1267,1271,1274],{"class":237,"line":238},[235,1268,1270],{"class":1269},"s6cf3","export",[235,1272,1273],{"class":1269}," default",[235,1275,1276],{"class":499}," {\n",[235,1278,1279,1282],{"class":237,"line":249},[235,1280,1281],{"class":495},"    state",[235,1283,1284],{"class":499},":{},\n",[235,1286,1287,1290,1292],{"class":237,"line":259},[235,1288,1289],{"class":495},"    getters",[235,1291,500],{"class":499},[235,1293,1294],{"class":499}," {},\n",[235,1296,1297,1300,1302],{"class":237,"line":266},[235,1298,1299],{"class":495},"    mutations",[235,1301,500],{"class":499},[235,1303,1294],{"class":499},[235,1305,1306,1309,1311],{"class":237,"line":275},[235,1307,1308],{"class":495},"    actions",[235,1310,500],{"class":499},[235,1312,841],{"class":499},[235,1314,1315],{"class":237,"line":283},[235,1316,1317],{"class":499},"}\n",[13,1319,1320],{},"storeはひとまず必要な型だけ準備します。",[226,1322,1325],{"className":1259,"code":1323,"filename":1324,"language":1262,"meta":231,"style":231},"import Home from '~js\u002Fvue\u002Fpage\u002FHome.vue';\nimport Profile from '~js\u002Fvue\u002Fpage\u002FProfile.vue';\n\nconst routes = [\n    { path: '\u002Fsystem', component: Home },\n    { path: '\u002Fsystem\u002Fprofile', component: Profile },\n]\n\nexport default routes;\n","router.js",[39,1326,1327,1349,1367,1371,1386,1415,1440,1445,1449],{"__ignoreMap":231},[235,1328,1329,1332,1335,1338,1340,1343,1346],{"class":237,"line":238},[235,1330,1331],{"class":1269},"import",[235,1333,1334],{"class":519}," Home ",[235,1336,1337],{"class":1269},"from",[235,1339,503],{"class":499},[235,1341,1342],{"class":245},"~js\u002Fvue\u002Fpage\u002FHome.vue",[235,1344,1345],{"class":499},"'",[235,1347,1348],{"class":499},";\n",[235,1350,1351,1353,1356,1358,1360,1363,1365],{"class":237,"line":249},[235,1352,1331],{"class":1269},[235,1354,1355],{"class":519}," Profile ",[235,1357,1337],{"class":1269},[235,1359,503],{"class":499},[235,1361,1362],{"class":245},"~js\u002Fvue\u002Fpage\u002FProfile.vue",[235,1364,1345],{"class":499},[235,1366,1348],{"class":499},[235,1368,1369],{"class":237,"line":259},[235,1370,263],{"emptyLinePlaceholder":262},[235,1372,1373,1377,1380,1383],{"class":237,"line":266},[235,1374,1376],{"class":1375},"sJ14y","const",[235,1378,1379],{"class":519}," routes ",[235,1381,1382],{"class":499},"=",[235,1384,1385],{"class":519}," [\n",[235,1387,1388,1391,1394,1396,1398,1400,1402,1405,1408,1410,1412],{"class":237,"line":275},[235,1389,1390],{"class":499},"    {",[235,1392,1393],{"class":495}," path",[235,1395,500],{"class":499},[235,1397,503],{"class":499},[235,1399,1022],{"class":245},[235,1401,1345],{"class":499},[235,1403,1404],{"class":499},",",[235,1406,1407],{"class":495}," component",[235,1409,500],{"class":499},[235,1411,1334],{"class":519},[235,1413,1414],{"class":499},"},\n",[235,1416,1417,1419,1421,1423,1425,1428,1430,1432,1434,1436,1438],{"class":237,"line":283},[235,1418,1390],{"class":499},[235,1420,1393],{"class":495},[235,1422,500],{"class":499},[235,1424,503],{"class":499},[235,1426,1427],{"class":245},"\u002Fsystem\u002Fprofile",[235,1429,1345],{"class":499},[235,1431,1404],{"class":499},[235,1433,1407],{"class":495},[235,1435,500],{"class":499},[235,1437,1355],{"class":519},[235,1439,1414],{"class":499},[235,1441,1442],{"class":237,"line":291},[235,1443,1444],{"class":519},"]\n",[235,1446,1447],{"class":237,"line":298},[235,1448,263],{"emptyLinePlaceholder":262},[235,1450,1451,1453,1455,1458],{"class":237,"line":380},[235,1452,1270],{"class":1269},[235,1454,1273],{"class":1269},[235,1456,1457],{"class":519}," routes",[235,1459,1348],{"class":499},[13,1461,1462,1463,1466],{},"router.jsでは指定のパスに対してどのコンポーネントを出すかを定義します。",[39,1464,1465],{},"~js","という記述は後で解説しますので、ひとまず記述してください。",[13,1468,1469],{},"router.jsで参照しているコンポーネントは以下の様にしておきます。",[226,1471,1475],{"className":1472,"code":1473,"filename":1474,"language":1208,"meta":231,"style":231},"language-vue shiki shiki-themes material-theme-ocean","\u003Ctemplate>\n    \u003Cdiv>\n        home\n        \u003Crouter-link to=\"\u002Fsystem\u002Fprofile\">profile\u003C\u002Frouter-link>\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\u003Cscript>\nexport default {\n    name:'home'\n}\n\u003C\u002Fscript>\n","Home.vue",[39,1476,1477,1488,1497,1502,1535,1544,1552,1561,1569,1583,1587],{"__ignoreMap":231},[235,1478,1479,1482,1485],{"class":237,"line":238},[235,1480,1481],{"class":499},"\u003C",[235,1483,1484],{"class":495},"template",[235,1486,1487],{"class":499},">\n",[235,1489,1490,1493,1495],{"class":237,"line":249},[235,1491,1492],{"class":499},"    \u003C",[235,1494,1225],{"class":495},[235,1496,1487],{"class":499},[235,1498,1499],{"class":237,"line":259},[235,1500,1501],{"class":519},"        home\n",[235,1503,1504,1507,1510,1513,1515,1518,1520,1522,1525,1528,1531,1533],{"class":237,"line":266},[235,1505,1506],{"class":499},"        \u003C",[235,1508,1509],{"class":495},"router-link",[235,1511,1512],{"class":1375}," to",[235,1514,1382],{"class":499},[235,1516,1517],{"class":499},"\"",[235,1519,1427],{"class":245},[235,1521,1517],{"class":499},[235,1523,1524],{"class":499},">",[235,1526,1527],{"class":519},"profile",[235,1529,1530],{"class":499},"\u003C\u002F",[235,1532,1509],{"class":495},[235,1534,1487],{"class":499},[235,1536,1537,1540,1542],{"class":237,"line":275},[235,1538,1539],{"class":499},"    \u003C\u002F",[235,1541,1225],{"class":495},[235,1543,1487],{"class":499},[235,1545,1546,1548,1550],{"class":237,"line":283},[235,1547,1530],{"class":499},[235,1549,1484],{"class":495},[235,1551,1487],{"class":499},[235,1553,1554,1556,1559],{"class":237,"line":291},[235,1555,1481],{"class":499},[235,1557,1558],{"class":495},"script",[235,1560,1487],{"class":499},[235,1562,1563,1565,1567],{"class":237,"line":298},[235,1564,1270],{"class":1269},[235,1566,1273],{"class":1269},[235,1568,1276],{"class":499},[235,1570,1571,1574,1576,1578,1581],{"class":237,"line":380},[235,1572,1573],{"class":495},"    name",[235,1575,500],{"class":499},[235,1577,1345],{"class":499},[235,1579,1580],{"class":245},"home",[235,1582,509],{"class":499},[235,1584,1585],{"class":237,"line":465},[235,1586,1317],{"class":499},[235,1588,1589,1591,1593],{"class":237,"line":590},[235,1590,1530],{"class":499},[235,1592,1558],{"class":495},[235,1594,1487],{"class":499},[226,1596,1599],{"className":1472,"code":1597,"filename":1598,"language":1208,"meta":231,"style":231},"\u003Ctemplate>\n    \u003Cdiv>\n        profile\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\u003Cscript>\nexport default {\n    name:'profile'\n}\n\u003C\u002Fscript>\n","Profile.vue",[39,1600,1601,1609,1617,1622,1630,1638,1646,1654,1666,1670],{"__ignoreMap":231},[235,1602,1603,1605,1607],{"class":237,"line":238},[235,1604,1481],{"class":499},[235,1606,1484],{"class":495},[235,1608,1487],{"class":499},[235,1610,1611,1613,1615],{"class":237,"line":249},[235,1612,1492],{"class":499},[235,1614,1225],{"class":495},[235,1616,1487],{"class":499},[235,1618,1619],{"class":237,"line":259},[235,1620,1621],{"class":519},"        profile\n",[235,1623,1624,1626,1628],{"class":237,"line":266},[235,1625,1539],{"class":499},[235,1627,1225],{"class":495},[235,1629,1487],{"class":499},[235,1631,1632,1634,1636],{"class":237,"line":275},[235,1633,1530],{"class":499},[235,1635,1484],{"class":495},[235,1637,1487],{"class":499},[235,1639,1640,1642,1644],{"class":237,"line":283},[235,1641,1481],{"class":499},[235,1643,1558],{"class":495},[235,1645,1487],{"class":499},[235,1647,1648,1650,1652],{"class":237,"line":291},[235,1649,1270],{"class":1269},[235,1651,1273],{"class":1269},[235,1653,1276],{"class":499},[235,1655,1656,1658,1660,1662,1664],{"class":237,"line":298},[235,1657,1573],{"class":495},[235,1659,500],{"class":499},[235,1661,1345],{"class":499},[235,1663,1527],{"class":245},[235,1665,509],{"class":499},[235,1667,1668],{"class":237,"line":380},[235,1669,1317],{"class":499},[235,1671,1672,1674,1676],{"class":237,"line":465},[235,1673,1530],{"class":499},[235,1675,1558],{"class":495},[235,1677,1487],{"class":499},[13,1679,1680],{},"index.jsは以下の様に記述します。",[226,1682,1685],{"className":1259,"code":1683,"filename":1684,"language":1262,"meta":231,"style":231},"window.axios = require('axios');\nwindow.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\n\nimport Vue from 'vue';\n\nimport Vuex from 'vuex';\nimport index from '.\u002Fstore';\nVue.use(Vuex);\nconst store = new Vuex.Store(index);\n\nimport VueRouter from 'vue-router'\nimport routes from '.\u002Frouter';\nVue.use(VueRouter)\nconst router =  new VueRouter({mode: 'history',routes})\n\nconst app = new Vue({\n    store,\n    router,\n}).$mount(\"#app\");\n","index.js",[39,1686,1687,1718,1762,1766,1783,1787,1805,1823,1838,1863,1867,1883,1900,1911,1954,1958,1977,1985,1992],{"__ignoreMap":231},[235,1688,1689,1692,1695,1698,1700,1703,1706,1708,1711,1713,1716],{"class":237,"line":238},[235,1690,1691],{"class":519},"window",[235,1693,1694],{"class":499},".",[235,1696,1697],{"class":519},"axios ",[235,1699,1382],{"class":499},[235,1701,1702],{"class":252}," require",[235,1704,1705],{"class":519},"(",[235,1707,1345],{"class":499},[235,1709,1710],{"class":245},"axios",[235,1712,1345],{"class":499},[235,1714,1715],{"class":519},")",[235,1717,1348],{"class":499},[235,1719,1720,1722,1724,1726,1728,1731,1733,1736,1738,1741,1743,1746,1748,1751,1753,1755,1758,1760],{"class":237,"line":249},[235,1721,1691],{"class":519},[235,1723,1694],{"class":499},[235,1725,1710],{"class":519},[235,1727,1694],{"class":499},[235,1729,1730],{"class":519},"defaults",[235,1732,1694],{"class":499},[235,1734,1735],{"class":519},"headers",[235,1737,1694],{"class":499},[235,1739,1740],{"class":519},"common[",[235,1742,1345],{"class":499},[235,1744,1745],{"class":245},"X-Requested-With",[235,1747,1345],{"class":499},[235,1749,1750],{"class":519},"] ",[235,1752,1382],{"class":499},[235,1754,503],{"class":499},[235,1756,1757],{"class":245},"XMLHttpRequest",[235,1759,1345],{"class":499},[235,1761,1348],{"class":499},[235,1763,1764],{"class":237,"line":259},[235,1765,263],{"emptyLinePlaceholder":262},[235,1767,1768,1770,1773,1775,1777,1779,1781],{"class":237,"line":266},[235,1769,1331],{"class":1269},[235,1771,1772],{"class":519}," Vue ",[235,1774,1337],{"class":1269},[235,1776,503],{"class":499},[235,1778,1208],{"class":245},[235,1780,1345],{"class":499},[235,1782,1348],{"class":499},[235,1784,1785],{"class":237,"line":275},[235,1786,263],{"emptyLinePlaceholder":262},[235,1788,1789,1791,1794,1796,1798,1801,1803],{"class":237,"line":283},[235,1790,1331],{"class":1269},[235,1792,1793],{"class":519}," Vuex ",[235,1795,1337],{"class":1269},[235,1797,503],{"class":499},[235,1799,1800],{"class":245},"vuex",[235,1802,1345],{"class":499},[235,1804,1348],{"class":499},[235,1806,1807,1809,1812,1814,1816,1819,1821],{"class":237,"line":291},[235,1808,1331],{"class":1269},[235,1810,1811],{"class":519}," index ",[235,1813,1337],{"class":1269},[235,1815,503],{"class":499},[235,1817,1818],{"class":245},".\u002Fstore",[235,1820,1345],{"class":499},[235,1822,1348],{"class":499},[235,1824,1825,1828,1830,1833,1836],{"class":237,"line":298},[235,1826,1827],{"class":519},"Vue",[235,1829,1694],{"class":499},[235,1831,1832],{"class":252},"use",[235,1834,1835],{"class":519},"(Vuex)",[235,1837,1348],{"class":499},[235,1839,1840,1842,1845,1847,1850,1853,1855,1858,1861],{"class":237,"line":380},[235,1841,1376],{"class":1375},[235,1843,1844],{"class":519}," store ",[235,1846,1382],{"class":499},[235,1848,1849],{"class":499}," new",[235,1851,1852],{"class":519}," Vuex",[235,1854,1694],{"class":499},[235,1856,1857],{"class":252},"Store",[235,1859,1860],{"class":519},"(index)",[235,1862,1348],{"class":499},[235,1864,1865],{"class":237,"line":465},[235,1866,263],{"emptyLinePlaceholder":262},[235,1868,1869,1871,1874,1876,1878,1881],{"class":237,"line":590},[235,1870,1331],{"class":1269},[235,1872,1873],{"class":519}," VueRouter ",[235,1875,1337],{"class":1269},[235,1877,503],{"class":499},[235,1879,1880],{"class":245},"vue-router",[235,1882,509],{"class":499},[235,1884,1885,1887,1889,1891,1893,1896,1898],{"class":237,"line":604},[235,1886,1331],{"class":1269},[235,1888,1379],{"class":519},[235,1890,1337],{"class":1269},[235,1892,503],{"class":499},[235,1894,1895],{"class":245},".\u002Frouter",[235,1897,1345],{"class":499},[235,1899,1348],{"class":499},[235,1901,1902,1904,1906,1908],{"class":237,"line":612},[235,1903,1827],{"class":519},[235,1905,1694],{"class":499},[235,1907,1832],{"class":252},[235,1909,1910],{"class":519},"(VueRouter)\n",[235,1912,1913,1915,1918,1920,1923,1926,1928,1931,1934,1936,1938,1941,1943,1945,1948,1951],{"class":237,"line":623},[235,1914,1376],{"class":1375},[235,1916,1917],{"class":519}," router ",[235,1919,1382],{"class":499},[235,1921,1922],{"class":499},"  new",[235,1924,1925],{"class":252}," VueRouter",[235,1927,1705],{"class":519},[235,1929,1930],{"class":499},"{",[235,1932,1933],{"class":495},"mode",[235,1935,500],{"class":499},[235,1937,503],{"class":499},[235,1939,1940],{"class":245},"history",[235,1942,1345],{"class":499},[235,1944,1404],{"class":499},[235,1946,1947],{"class":519},"routes",[235,1949,1950],{"class":499},"}",[235,1952,1953],{"class":519},")\n",[235,1955,1956],{"class":237,"line":634},[235,1957,263],{"emptyLinePlaceholder":262},[235,1959,1960,1962,1965,1967,1969,1972,1974],{"class":237,"line":641},[235,1961,1376],{"class":1375},[235,1963,1964],{"class":519}," app ",[235,1966,1382],{"class":499},[235,1968,1849],{"class":499},[235,1970,1971],{"class":252}," Vue",[235,1973,1705],{"class":519},[235,1975,1976],{"class":499},"{\n",[235,1978,1979,1982],{"class":237,"line":653},[235,1980,1981],{"class":519},"    store",[235,1983,1984],{"class":499},",\n",[235,1986,1987,1990],{"class":237,"line":661},[235,1988,1989],{"class":519},"    router",[235,1991,1984],{"class":499},[235,1993,1994,1996,1998,2000,2003,2005,2007,2010,2012,2014],{"class":237,"line":670},[235,1995,1950],{"class":499},[235,1997,1715],{"class":519},[235,1999,1694],{"class":499},[235,2001,2002],{"class":252},"$mount",[235,2004,1705],{"class":519},[235,2006,1517],{"class":499},[235,2008,2009],{"class":245},"#app",[235,2011,1517],{"class":499},[235,2013,1715],{"class":519},[235,2015,1348],{"class":499},[13,2017,2018,2019,2022],{},"axiosはLaravelインストール時に入っているのでそのまま利用しています。このファイルではVuexとVue-routerの連携を行い、最終的に",[39,2020,2021],{},"\u003Cdiv id=\"app\">\u003C\u002Fdiv>","にレンダリングされる様にします。",[13,2024,2025,2026,2029],{},"上記のファイルを作成した後、",[39,2027,2028],{},"webpac.mix.js","を修正します。",[81,2031,2032],{"id":2032},"mixファイルの作成",[13,2034,2035,2036,2039,2040,2043,2044,2047,2048,2051],{},"このようなVueのプロジェクトwebpackを使用しますがLaravelは簡単な記述で",[39,2037,2038],{},"resources","配下を簡単に",[39,2041,2042],{},"public\u002F","配下に出力してくれます。またvueやsassのコンパイル設定を",[39,2045,2046],{},"webpack.config.js","の様に書く必要がありません。どのファイルをコンパイル対象にするかなどは",[39,2049,2050],{},"webpack.mix.js","に記載します。以下の様に修正します。",[226,2053,2055],{"className":1259,"code":2054,"filename":2046,"language":1262,"meta":231,"style":231},"const mix = require('laravel-mix');\nconst path = require('path');\n\nmix.webpackConfig({\n    resolve: {\n      alias: {\n        '~js': path.resolve('.\u002Fresources\u002Fjs'),\n      }\n    }\n});\nmix.js('resources\u002Fjs\u002Fadmin\u002Findex.js', 'public\u002Fjs\u002Fadmin').vue();\n",[39,2056,2057,2081,2105,2109,2123,2132,2141,2172,2177,2182,2190],{"__ignoreMap":231},[235,2058,2059,2061,2064,2066,2068,2070,2072,2075,2077,2079],{"class":237,"line":238},[235,2060,1376],{"class":1375},[235,2062,2063],{"class":519}," mix ",[235,2065,1382],{"class":499},[235,2067,1702],{"class":252},[235,2069,1705],{"class":519},[235,2071,1345],{"class":499},[235,2073,2074],{"class":245},"laravel-mix",[235,2076,1345],{"class":499},[235,2078,1715],{"class":519},[235,2080,1348],{"class":499},[235,2082,2083,2085,2088,2090,2092,2094,2096,2099,2101,2103],{"class":237,"line":249},[235,2084,1376],{"class":1375},[235,2086,2087],{"class":519}," path ",[235,2089,1382],{"class":499},[235,2091,1702],{"class":252},[235,2093,1705],{"class":519},[235,2095,1345],{"class":499},[235,2097,2098],{"class":245},"path",[235,2100,1345],{"class":499},[235,2102,1715],{"class":519},[235,2104,1348],{"class":499},[235,2106,2107],{"class":237,"line":259},[235,2108,263],{"emptyLinePlaceholder":262},[235,2110,2111,2114,2116,2119,2121],{"class":237,"line":266},[235,2112,2113],{"class":519},"mix",[235,2115,1694],{"class":499},[235,2117,2118],{"class":252},"webpackConfig",[235,2120,1705],{"class":519},[235,2122,1976],{"class":499},[235,2124,2125,2128,2130],{"class":237,"line":275},[235,2126,2127],{"class":495},"    resolve",[235,2129,500],{"class":499},[235,2131,1276],{"class":499},[235,2133,2134,2137,2139],{"class":237,"line":283},[235,2135,2136],{"class":495},"      alias",[235,2138,500],{"class":499},[235,2140,1276],{"class":499},[235,2142,2143,2146,2148,2150,2152,2154,2156,2159,2161,2163,2166,2168,2170],{"class":237,"line":291},[235,2144,2145],{"class":499},"        '",[235,2147,1465],{"class":495},[235,2149,1345],{"class":499},[235,2151,500],{"class":499},[235,2153,1393],{"class":519},[235,2155,1694],{"class":499},[235,2157,2158],{"class":252},"resolve",[235,2160,1705],{"class":519},[235,2162,1345],{"class":499},[235,2164,2165],{"class":245},".\u002Fresources\u002Fjs",[235,2167,1345],{"class":499},[235,2169,1715],{"class":519},[235,2171,1984],{"class":499},[235,2173,2174],{"class":237,"line":298},[235,2175,2176],{"class":499},"      }\n",[235,2178,2179],{"class":237,"line":380},[235,2180,2181],{"class":499},"    }\n",[235,2183,2184,2186,2188],{"class":237,"line":465},[235,2185,1950],{"class":499},[235,2187,1715],{"class":519},[235,2189,1348],{"class":499},[235,2191,2192,2194,2196,2198,2200,2202,2205,2207,2209,2211,2214,2216,2218,2220,2222,2225],{"class":237,"line":590},[235,2193,2113],{"class":519},[235,2195,1694],{"class":499},[235,2197,1262],{"class":252},[235,2199,1705],{"class":519},[235,2201,1345],{"class":499},[235,2203,2204],{"class":245},"resources\u002Fjs\u002Fadmin\u002Findex.js",[235,2206,1345],{"class":499},[235,2208,1404],{"class":499},[235,2210,503],{"class":499},[235,2212,2213],{"class":245},"public\u002Fjs\u002Fadmin",[235,2215,1345],{"class":499},[235,2217,1715],{"class":519},[235,2219,1694],{"class":499},[235,2221,1208],{"class":252},[235,2223,2224],{"class":519},"()",[235,2226,1348],{"class":499},[13,2228,2229,2232,2233,2235],{},[39,2230,2231],{},"mix.webpackConfig","はのように",[39,2234,2046],{},"に書く様な他の細かいwebpackの設定を定義でき、ここではエイリアスを定義しています。",[13,2237,2238,2241,2242,2244,2245,2247],{},[39,2239,2240],{},"'~js': path.resolve('.\u002Fresources\u002Fjs')","という記述は",[39,2243,1465],{},"というパスの記載があった場合は「",[39,2246,1246],{},"までの絶対ルート」であるとwebpackに支持しています。この様にエイリアスを定義することで相対パスによるファイルの参照がなくなります。router.jsで以下の様に定義していましたが、",[226,2249,2251],{"className":1259,"code":2250,"filename":1324,"language":1262,"meta":231,"style":231},"import Home from '~js\u002Fvue\u002Fpage\u002FHome.vue';\nimport Profile from '~js\u002Fvue\u002Fpage\u002FProfile.vue';\n",[39,2252,2253,2269],{"__ignoreMap":231},[235,2254,2255,2257,2259,2261,2263,2265,2267],{"class":237,"line":238},[235,2256,1331],{"class":1269},[235,2258,1334],{"class":519},[235,2260,1337],{"class":1269},[235,2262,503],{"class":499},[235,2264,1342],{"class":245},[235,2266,1345],{"class":499},[235,2268,1348],{"class":499},[235,2270,2271,2273,2275,2277,2279,2281,2283],{"class":237,"line":249},[235,2272,1331],{"class":1269},[235,2274,1355],{"class":519},[235,2276,1337],{"class":1269},[235,2278,503],{"class":499},[235,2280,1362],{"class":245},[235,2282,1345],{"class":499},[235,2284,1348],{"class":499},[13,2286,2287],{},"もしエイリアスが使えない場合は",[226,2289,2291],{"className":1259,"code":2290,"filename":1324,"language":1262,"meta":231,"style":231},"import Home from '..\u002Fvue\u002Fpage\u002FHome.vue';\nimport Profile from '..\u002Fvue\u002Fpage\u002FProfile.vue';\n",[39,2292,2293,2310],{"__ignoreMap":231},[235,2294,2295,2297,2299,2301,2303,2306,2308],{"class":237,"line":238},[235,2296,1331],{"class":1269},[235,2298,1334],{"class":519},[235,2300,1337],{"class":1269},[235,2302,503],{"class":499},[235,2304,2305],{"class":245},"..\u002Fvue\u002Fpage\u002FHome.vue",[235,2307,1345],{"class":499},[235,2309,1348],{"class":499},[235,2311,2312,2314,2316,2318,2320,2323,2325],{"class":237,"line":249},[235,2313,1331],{"class":1269},[235,2315,1355],{"class":519},[235,2317,1337],{"class":1269},[235,2319,503],{"class":499},[235,2321,2322],{"class":245},"..\u002Fvue\u002Fpage\u002FProfile.vue",[235,2324,1345],{"class":499},[235,2326,1348],{"class":499},[13,2328,2329,2330,2332],{},"このように相対パスになってしまい、もし構成を変えようとした時に相対関係の修正が必要となります。その対策としてエイリアスを定めておくと今後の管理がしやすいです。",[39,2331,2240],{},"はjsディレクトリを参照する様にしています。",[13,2334,2335,2338,2339,2341,2342,2345],{},[39,2336,2337],{},"mix.js('resources\u002Fjs\u002Fadmin\u002Findex.js', 'public\u002Fjs\u002Fadmin').vue();"," にて",[39,2340,1684],{},"をソースとして",[39,2343,2344],{},"'public\u002Fjs\u002Fadmin'","配下に出力し、vueコンパイルを行う様に定義してます。",[13,2347,2348,2349,2352,2353,2356],{},"問題なければ",[39,2350,2351],{},"npm run prod","をプロジェクト ルートでコマンドを叩いてコンパイルを行います。完了後に",[39,2354,2355],{},"public\u002Fjs\u002Fadmin\u002Findex.js","というものが出力されていることを確認してください。",[81,2358,2359],{"id":2359},"反映の確認",[13,2361,2362,2363,2366,2367,2369,2370,2372],{},"jsファイルが出力されましたら",[39,2364,2365],{},"http:\u002F\u002Flocalhost:8005\u002Fsystem","にアクセスします。以下の様に表示され、",[39,2368,1527],{},"というリンクをクリックした際にURLが変わり、",[39,2371,1598],{},"に書かれた内容が表示されればSPAはできています。",[183,2374],{":src":2375,":center":186},"'vue_laravel_app\u002Fhomevue.png'",[13,2377,2378,2380,2381,2384],{},[39,2379,1527],{},"というリンクをクリック後 or ",[39,2382,2383],{},"http:\u002F\u002Flocalhost:8005\u002Fsystem\u002Fprofile","にアクセスしますと以下の様になります。",[183,2386],{":src":2387,":center":186},"'vue_laravel_app\u002Fprofilevue.png'",[13,2389,2390],{},"これでSPAが設定できたことを確認できました。",[74,2392,2394],{"id":2393},"次回は","次回は..",[13,2396,2397],{},"今回は環境構築とLaravel、Vue SPAのセットアップまでとなります。来週はweb apiを通じたSPAでの認証と簡単なプロフィールの更新機能を作成してみます。",[2399,2400,2401],"style",{},"html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}",{"title":231,"searchDepth":259,"depth":259,"links":2403},[2404,2412,2417,2418,2425],{"id":76,"depth":249,"text":76,"children":2405},[2406,2411],{"id":83,"depth":259,"text":83,"children":2407},[2408,2409,2410],{"id":90,"depth":266,"text":90},{"id":124,"depth":266,"text":124},{"id":164,"depth":266,"text":164},{"id":178,"depth":259,"text":178},{"id":192,"depth":249,"text":192,"children":2413},[2414,2415,2416],{"id":325,"depth":259,"text":326},{"id":389,"depth":259,"text":389},{"id":478,"depth":259,"text":479},{"id":989,"depth":249,"text":990},{"id":1009,"depth":249,"text":1010,"children":2419},[2420,2421,2422,2423,2424],{"id":1016,"depth":259,"text":1017},{"id":1198,"depth":259,"text":1198},{"id":1239,"depth":259,"text":1240},{"id":2032,"depth":259,"text":2032},{"id":2359,"depth":259,"text":2359},{"id":2393,"depth":249,"text":2394},[2427],"devstack","2022-03-02","アプリの解説とシリーズの概要","md",{},"\u002Fseries\u002Fvue-laravel-app-1",{"title":8,"description":2429},"vue_laravel_app","Vue SPA x Laravelでつくる実務パチモンアプリ","series\u002Fvue-laravel-app-1",[971,1029,1262,1208],"vue_laravel_app\u002Fseries.png",null,"QS_7_9yqTbYmh1Gt9XAVtEnkXBXd1wzlct80a3xdm_U",{"id":2442,"title":2443,"body":2444,"category":3868,"createdAt":3869,"description":2429,"extension":2430,"index":238,"meta":3870,"navigation":262,"path":3871,"publish":262,"seo":3872,"series":3873,"seriesTitle":3874,"stem":3875,"tag":3876,"thumbnail":3878,"updatedAt":2439,"__hash__":3879},"series\u002Fseries\u002Flaravel-to-django-1.md","Laravel使いがDjangoでwebアプリを作るよその１：アプリの概要と環境構築",{"type":10,"value":2445,"toc":3848},[2446,2449,2452,2455,2466,2469,2472,2475,2495,2498,2501,2520,2522,2528,2569,2576,2579,2582,2623,2626,2628,2633,2906,2911,2921,2935,2942,2959,2982,2987,2993,3008,3012,3015,3018,3020,3042,3044,3073,3075,3083,3086,3089,3093,3096,3099,3110,3171,3174,3230,3243,3246,3249,3324,3340,3343,3356,3636,3639,3657,3660,3667,3673,3680,3686,3696,3704,3715,3734,3740,3749,3752,3803,3810,3839,3842,3845],[13,2447,2448],{},"こんにちはjunです。最近Laravelでシステムを作る機会が何回かあったので、Laravelによる構築がかなり得意になってきました。しかし会社の方で「pythonを使用した機械学習や統計の機能をwebアプリとして使用できるアプリを開発したい」という企画がでてきました。",[13,2450,2451],{},"pythonで機械学習や統計の処理（モデル）を作成し、UIやロジックの部分をwebフレームワークで作成します。できたらwebフレームワークの処理部分にて統計ロジックをimportして、データの引き渡しを行いたいと思いました。しかしLaravelはPHPなので連携が難しいです。",[13,2453,2454],{},"そのため「Python製のwebフレームワークであるdjangoを利用できないか？」と思い、Djangoの勉強をスタートしました。チュートリアルはひとまず終えましたが、Laravelをやっていたおかげで",[17,2456,2457,2460,2463],{},[20,2458,2459],{},"どんな機能があると便利か？",[20,2461,2462],{},"Laravelのこの機能がDjangoのこの記述にあたるのか？",[20,2464,2465],{},"実務上必要となるこの機能を実装するには何を使えばいいのか？",[13,2467,2468],{},"という視点を用いて学習することができました。このシリーズでは「Laravelを使っていたPHP開発者がDjangoとPythonを使用してアプリを作る」ことを通じてDjangoの学習をしたいと思っています。記事内ではDjangoにおける実装とLaravelにおける実装をリンクしながら解説していきたいと思います。",[13,2470,2471],{},"利用するDjangoのバージョンは3.2で、Laravelは8とします。第１回のこの記事は環境構築とアプリの概要、Djangoの開発コンセプトやディレクトリ説明がメインとなります。",[13,2473,2474],{},"なおシリーズでは以下の内容を押さえていることを前提としています",[17,2476,2477,2480,2483,2486,2489,2492],{},[20,2478,2479],{},"Laravelの実務開発経験があるまたは、完成したアプリを作ったことがある。",[20,2481,2482],{},"Laravelのコンセプトやディレクトリ構成を知っている。",[20,2484,2485],{},"PythonがPCにインストールされ、基本的な記述を理解している。",[20,2487,2488],{},"PHPを触ったことが多いが、Pythonはそれほどない。",[20,2490,2491],{},"Djangoのチュートリアルは行っており、必須の内容は知っている。",[20,2493,2494],{},"MVCの概念を知っている、使える。",[13,2496,2497],{},"それでは早速始めていきましょう。",[13,2499,2500],{},"参考資料",[17,2502,2503,2510,2513],{},[20,2504,2505],{},[197,2506,2509],{"href":2507,"rel":2508},"https:\u002F\u002Fdocs.djangoproject.com\u002Fja\u002F3.2",[201],"Django ドキュメント3.2",[20,2511,2512],{},"書籍『現場で使える Django の教科書』",[20,2514,2515],{},[197,2516,2519],{"href":2517,"rel":2518},"https:\u002F\u002Fdocs.docker.jp\u002Fcompose\u002Fdjango.html",[201],"クィックスタート: Compose と Django - Docker ドキュメント",[74,2521,192],{"id":192},[13,2523,2524,2525,2527],{},"今回の環境構築はdockerを用いて作成しようと思います。適当なディレクトリ を作成し、",[39,2526,223],{},"とビルドファイルを作成します。",[226,2529,2531],{"className":228,"code":2530,"language":230,"meta":231,"style":231},"mkdir laravel_django\ncd laravel_django\n\ntouch Dockerfile\ntouch docker-compose.yaml\nmkdir source\n",[39,2532,2533,2540,2546,2550,2556,2562],{"__ignoreMap":231},[235,2534,2535,2537],{"class":237,"line":238},[235,2536,242],{"class":241},[235,2538,2539],{"class":245}," laravel_django\n",[235,2541,2542,2544],{"class":237,"line":249},[235,2543,253],{"class":252},[235,2545,2539],{"class":245},[235,2547,2548],{"class":237,"line":259},[235,2549,263],{"emptyLinePlaceholder":262},[235,2551,2552,2554],{"class":237,"line":266},[235,2553,269],{"class":241},[235,2555,303],{"class":245},[235,2557,2558,2560],{"class":237,"line":275},[235,2559,269],{"class":241},[235,2561,272],{"class":245},[235,2563,2564,2566],{"class":237,"line":283},[235,2565,242],{"class":241},[235,2567,2568],{"class":245}," source\n",[13,2570,2571,2572,2575],{},"まずはDockerfileでDjangoが稼働するpythonの環境を作成します。なお、この環境ではApacheやnginxといったwebサーバーとpythonとの連携設定は行わないものとします。コンテナ内で",[39,2573,2574],{},"run serve","を行います。",[81,2577,316],{"id":2578},"dockerfile",[13,2580,2581],{},"Dockerfileを以下の様に記述します。",[226,2583,2586],{"className":2584,"code":2585,"language":316,"meta":231,"style":231},"language-Dockerfile shiki shiki-themes material-theme-ocean","FROM python:3\nENV PYTHONUNBUFFERED 1\nRUN mkdir \u002Fcode\nWORKDIR \u002Fcode\nADD requirements.txt \u002Fcode\u002F\nRUN pip install -r requirements.txt\nADD . \u002Fcode\u002F\n",[39,2587,2588,2593,2598,2603,2608,2613,2618],{"__ignoreMap":231},[235,2589,2590],{"class":237,"line":238},[235,2591,2592],{},"FROM python:3\n",[235,2594,2595],{"class":237,"line":249},[235,2596,2597],{},"ENV PYTHONUNBUFFERED 1\n",[235,2599,2600],{"class":237,"line":259},[235,2601,2602],{},"RUN mkdir \u002Fcode\n",[235,2604,2605],{"class":237,"line":266},[235,2606,2607],{},"WORKDIR \u002Fcode\n",[235,2609,2610],{"class":237,"line":275},[235,2611,2612],{},"ADD requirements.txt \u002Fcode\u002F\n",[235,2614,2615],{"class":237,"line":283},[235,2616,2617],{},"RUN pip install -r requirements.txt\n",[235,2619,2620],{"class":237,"line":291},[235,2621,2622],{},"ADD . \u002Fcode\u002F\n",[13,2624,2625],{},"python3 イメージをもとにpythonが動く環境を用意します。",[81,2627,877],{"id":877},[13,2629,2630,2632],{},[39,2631,223],{},"は以下の様に記述します。",[226,2634,2636],{"className":485,"code":2635,"filename":223,"language":488,"meta":231,"style":231},"version: '3'\n\nservices:\n  db:\n    image: mysql:5.7\n    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci\n    environment:\n      MYSQL_DATABASE: preform\n      MYSQL_USER: test\n      MYSQL_PASSWORD: testtest\n      MYSQL_ROOT_PASSWORD: rootroot\n      TZ: Asia\u002FTokyo\n    ports: \n      - \"3306:3306\"\n    volumes: \n      - djangodemo:\u002Fvar\u002Flib\u002Fmysql\n  phpmyadmin:\n    image: phpmyadmin\n    ports:\n      - \"8080:80\"\n    environment:\n     - PMA_ARBITRARY=1\n     - PMA_HOST=db:3306\n     - PMA_USER=root\n     - PMA_PASSWORD=rootroot\n  web:\n    build: .\n    command: python3 manage.py runserver 0.0.0.0:8000\n    volumes:\n      - .\u002Fsource:\u002Fcode\n    ports:\n      - \"8000:8000\"\n    depends_on:\n      - db\nvolumes: \n  djangodemo: {}\n",[39,2637,2638,2650,2654,2660,2666,2674,2682,2688,2696,2704,2712,2720,2728,2736,2746,2754,2761,2767,2775,2781,2791,2797,2803,2809,2815,2821,2828,2838,2847,2853,2860,2866,2877,2883,2889,2897],{"__ignoreMap":231},[235,2639,2640,2642,2644,2646,2648],{"class":237,"line":238},[235,2641,496],{"class":495},[235,2643,500],{"class":499},[235,2645,503],{"class":499},[235,2647,506],{"class":245},[235,2649,509],{"class":499},[235,2651,2652],{"class":237,"line":249},[235,2653,263],{"emptyLinePlaceholder":262},[235,2655,2656,2658],{"class":237,"line":259},[235,2657,514],{"class":495},[235,2659,528],{"class":499},[235,2661,2662,2664],{"class":237,"line":266},[235,2663,697],{"class":495},[235,2665,528],{"class":499},[235,2667,2668,2670,2672],{"class":237,"line":275},[235,2669,615],{"class":495},[235,2671,500],{"class":499},[235,2673,709],{"class":245},[235,2675,2676,2678,2680],{"class":237,"line":283},[235,2677,715],{"class":495},[235,2679,500],{"class":499},[235,2681,720],{"class":245},[235,2683,2684,2686],{"class":237,"line":291},[235,2685,656],{"class":495},[235,2687,528],{"class":499},[235,2689,2690,2692,2694],{"class":237,"line":298},[235,2691,733],{"class":495},[235,2693,500],{"class":499},[235,2695,738],{"class":245},[235,2697,2698,2700,2702],{"class":237,"line":380},[235,2699,744],{"class":495},[235,2701,500],{"class":499},[235,2703,749],{"class":245},[235,2705,2706,2708,2710],{"class":237,"line":465},[235,2707,755],{"class":495},[235,2709,500],{"class":499},[235,2711,760],{"class":245},[235,2713,2714,2716,2718],{"class":237,"line":590},[235,2715,766],{"class":495},[235,2717,500],{"class":499},[235,2719,771],{"class":245},[235,2721,2722,2724,2726],{"class":237,"line":604},[235,2723,777],{"class":495},[235,2725,500],{"class":499},[235,2727,782],{"class":245},[235,2729,2730,2732,2734],{"class":237,"line":612},[235,2731,583],{"class":495},[235,2733,500],{"class":499},[235,2735,520],{"class":519},[235,2737,2738,2740,2742,2744],{"class":237,"line":623},[235,2739,552],{"class":499},[235,2741,595],{"class":499},[235,2743,801],{"class":245},[235,2745,601],{"class":499},[235,2747,2748,2750,2752],{"class":237,"line":634},[235,2749,560],{"class":495},[235,2751,500],{"class":499},[235,2753,520],{"class":519},[235,2755,2756,2758],{"class":237,"line":641},[235,2757,552],{"class":499},[235,2759,2760],{"class":245}," djangodemo:\u002Fvar\u002Flib\u002Fmysql\n",[235,2762,2763,2765],{"class":237,"line":653},[235,2764,607],{"class":495},[235,2766,528],{"class":499},[235,2768,2769,2771,2773],{"class":237,"line":661},[235,2770,615],{"class":495},[235,2772,500],{"class":499},[235,2774,620],{"class":245},[235,2776,2777,2779],{"class":237,"line":670},[235,2778,583],{"class":495},[235,2780,528],{"class":499},[235,2782,2783,2785,2787,2789],{"class":237,"line":678},[235,2784,552],{"class":499},[235,2786,595],{"class":499},[235,2788,648],{"class":245},[235,2790,601],{"class":499},[235,2792,2793,2795],{"class":237,"line":686},[235,2794,656],{"class":495},[235,2796,528],{"class":499},[235,2798,2799,2801],{"class":237,"line":694},[235,2800,664],{"class":499},[235,2802,667],{"class":245},[235,2804,2805,2807],{"class":237,"line":702},[235,2806,664],{"class":499},[235,2808,675],{"class":245},[235,2810,2811,2813],{"class":237,"line":712},[235,2812,664],{"class":499},[235,2814,683],{"class":245},[235,2816,2817,2819],{"class":237,"line":723},[235,2818,664],{"class":499},[235,2820,691],{"class":245},[235,2822,2823,2826],{"class":237,"line":730},[235,2824,2825],{"class":495},"  web",[235,2827,528],{"class":499},[235,2829,2830,2832,2834],{"class":237,"line":741},[235,2831,533],{"class":495},[235,2833,500],{"class":499},[235,2835,2837],{"class":2836},"sx098"," .\n",[235,2839,2840,2842,2844],{"class":237,"line":752},[235,2841,715],{"class":495},[235,2843,500],{"class":499},[235,2845,2846],{"class":245}," python3 manage.py runserver 0.0.0.0:8000\n",[235,2848,2849,2851],{"class":237,"line":763},[235,2850,560],{"class":495},[235,2852,528],{"class":499},[235,2854,2855,2857],{"class":237,"line":774},[235,2856,552],{"class":499},[235,2858,2859],{"class":245}," .\u002Fsource:\u002Fcode\n",[235,2861,2862,2864],{"class":237,"line":785},[235,2863,583],{"class":495},[235,2865,528],{"class":499},[235,2867,2868,2870,2872,2875],{"class":237,"line":794},[235,2869,552],{"class":499},[235,2871,595],{"class":499},[235,2873,2874],{"class":245},"8000:8000",[235,2876,601],{"class":499},[235,2878,2879,2881],{"class":237,"line":806},[235,2880,543],{"class":495},[235,2882,528],{"class":499},[235,2884,2885,2887],{"class":237,"line":815},[235,2886,552],{"class":499},[235,2888,555],{"class":245},[235,2890,2891,2893,2895],{"class":237,"line":823},[235,2892,826],{"class":495},[235,2894,500],{"class":499},[235,2896,520],{"class":519},[235,2898,2899,2902,2904],{"class":237,"line":833},[235,2900,2901],{"class":495},"  djangodemo",[235,2903,500],{"class":499},[235,2905,841],{"class":499},[13,2907,2908,2910],{},[39,2909,866],{},"ではデータベースを定義しています。DjangoはSQLiteを使用した簡易的なDBが用意されています。ただし実務ではmysqlなどのDBサーバーを使用することが多いので、今回はmysqlを使用できる様にします。",[1225,2912,2915,2916],{"className":2913},[1228,2914],"alert-info","\nDjangoでmysqlを使用するためにはpythonモジュールのmysqlclientが必要です。この環境にはデフォルトでないので注意してください。他のDBサーバーを使用する場合は適宜ドライバをインストールしてください。\n",[197,2917,2920],{"target":2918,"href":2919},"_blank","https:\u002F\u002Fdocs.djangoproject.com\u002Fja\u002F3.2\u002Ftopics\u002Finstall\u002F#get-your-database-running","本家ドキュメントを参照",[13,2922,2923,2924,2927,2928,2930,2931,2934],{},"DB内部をすぐに確認できる様にphpmyadminを入れておきます。（好みなのでなくてもいいです。）\nそして",[39,2925,2926],{},"web","では同階層にある",[39,2929,316],{},"をビルドして実行できる様になります。立ち上げ時に",[39,2932,2933],{},"python3 manage.py runserver 0.0.0.0:8000","をしてwebサーバを立ち上げる設定にしています。",[13,2936,2937,2938,2941],{},"このコンテナを起動する前に ",[39,2939,2940],{},"requirements.txt"," をDockerfileと同じ階層に生成しておき、以下の内容を記述します。",[226,2943,2947],{"className":2944,"code":2945,"filename":2940,"language":2946,"meta":231,"style":231},"language-txt shiki shiki-themes material-theme-ocean","Django==3.2\nmysqlclient==2.1.0\n","txt",[39,2948,2949,2954],{"__ignoreMap":231},[235,2950,2951],{"class":237,"line":238},[235,2952,2953],{},"Django==3.2\n",[235,2955,2956],{"class":237,"line":249},[235,2957,2958],{},"mysqlclient==2.1.0\n",[13,2960,2961,2963,2964,2967,2968,2971,2972,2974,2975,2977,2978,2981],{},[39,2962,2940],{}," はpythonライブラリ管理ツールpipの設定ファイルです。npmの",[39,2965,2966],{},"package.json","やcomposerの",[39,2969,2970],{},"composer.json","といったものと同じです。pythonのモジュール管理はpipを使用することが多く、",[39,2973,2940],{}," は環境ないの依存するモジュールとそのバージョンを記述して配置しておきます。そして",[39,2976,2940],{}," がある階層で ",[39,2979,2980],{},"pip install","をすることで自動的に依存関係をインストールしてくれます。Django3.2とmysqlclientを記述しておきます。",[13,2983,2984,2986],{},[39,2985,2940],{},"を記述したら以下のコマンドを実行してDjangoのソースを作成します。",[226,2988,2991],{"className":2989,"code":2990,"language":934},[932],"docker-compose run web django-admin.py startproject djangodemo .\n",[39,2992,2990],{"__ignoreMap":231},[13,2994,2995,2996,2999,3000,3003,3004,3007],{},"すると",[39,2997,2998],{},"source\u002F","配下にDjangoのソースが生成されるはずです。\nそして準備が整ったら",[39,3001,3002],{},"docker-compose up -d --build"," を行って構築を行います。問題なくいった場合はブラウザにて ",[39,3005,3006],{},"localhost:8000"," を閲覧すると、Djangoのウェルカムページが表示されるはずです。",[183,3009],{":src":3010,":width":3011},"'laralve_to_django\u002Fwelcome.png'","'100%'",[74,3013,3014],{"id":3014},"アプリ概要",[13,3016,3017],{},"今回作成するアプリはn○teみたいなブログサービスを作成しようと思います。",[88,3019,90],{"id":90},[17,3021,3022,3024,3026,3028,3030,3032],{},[20,3023,95],{},[20,3025,98],{},[20,3027,101],{},[20,3029,104],{},[20,3031,107],{},[20,3033,110,3034],{},[17,3035,3036,3038,3040],{},[20,3037,115],{},[20,3039,118],{},[20,3041,121],{},[88,3043,124],{"id":124},[17,3045,3046,3048,3060,3062,3064,3066,3068,3070],{},[20,3047,129],{},[20,3049,132,3050],{},[17,3051,3052,3054,3056,3058],{},[20,3053,137],{},[20,3055,140],{},[20,3057,143],{},[20,3059,146],{},[20,3061,149],{},[20,3063,152],{},[20,3065,155],{},[20,3067,158],{},[20,3069,161],{},[20,3071,3072],{},"公開側からコメント可能",[88,3074,164],{"id":164},[17,3076,3077,3079,3081],{},[20,3078,169],{},[20,3080,172],{},[20,3082,175],{},[13,3084,3085],{},"一通りユーザーエンティティから、記事のCURD、リレーションの練習はできると思います。すべてのビューはpython側でレンダリングを行い、Vue.jsなどは今回使用しません。違う機会にrest apiを使用した構成を作ってみたいとおおいます。",[13,3087,3088],{},"デザインに関してはいつものbootstrapを使用します。",[74,3090,3092],{"id":3091},"djangoの大まかな解説","Djangoの大まかな解説",[13,3094,3095],{},"詳細なロジックなどは次の記事で解説したいと思います。今回はDjangoのディレクトリ構成やLaravelと似ているとこやリンクしている中核的な機能を解説したいと思います。",[81,3097,3098],{"id":3098},"コマンドによる制御",[13,3100,3101,3102,3105,3106,3109],{},"Laravelでは ",[39,3103,3104],{},"php artisan"," を使用することでコントローラーを作ったり、マイグレーションを実行したりできます。Djangoにも似た様なものがあります。使用する時はソーストップの ",[39,3107,3108],{},"manage.py"," がある箇所で実行します。例えば以下の様な機能があります。",[226,3111,3113],{"className":228,"code":3112,"language":230,"meta":231,"style":231},"# 簡易webサーバーを起動\npython3 manage.py runserve\n\n# マイグレーションを実行\npython3 manage.py migrate\n\n# アプリのテンプレートを作成\npython3 manage.py startapp APP_NAME\n\n",[39,3114,3115,3121,3132,3136,3141,3150,3154,3159],{"__ignoreMap":231},[235,3116,3117],{"class":237,"line":238},[235,3118,3120],{"class":3119},"sC9rS","# 簡易webサーバーを起動\n",[235,3122,3123,3126,3129],{"class":237,"line":249},[235,3124,3125],{"class":241},"python3",[235,3127,3128],{"class":245}," manage.py",[235,3130,3131],{"class":245}," runserve\n",[235,3133,3134],{"class":237,"line":259},[235,3135,263],{"emptyLinePlaceholder":262},[235,3137,3138],{"class":237,"line":266},[235,3139,3140],{"class":3119},"# マイグレーションを実行\n",[235,3142,3143,3145,3147],{"class":237,"line":275},[235,3144,3125],{"class":241},[235,3146,3128],{"class":245},[235,3148,3149],{"class":245}," migrate\n",[235,3151,3152],{"class":237,"line":283},[235,3153,263],{"emptyLinePlaceholder":262},[235,3155,3156],{"class":237,"line":291},[235,3157,3158],{"class":3119},"# アプリのテンプレートを作成\n",[235,3160,3161,3163,3165,3168],{"class":237,"line":298},[235,3162,3125],{"class":241},[235,3164,3128],{"class":245},[235,3166,3167],{"class":245}," startapp",[235,3169,3170],{"class":245}," APP_NAME\n",[13,3172,3173],{},"Laravelで例えると",[226,3175,3177],{"className":228,"code":3176,"language":230,"meta":231,"style":231},"# 簡易webサーバーを起動\nphp artisan serve\n\n# マイグレーションを実行\nphp artisan migrate\n\n# コントローラーのテンプレートを作成\nphp artisan make:controller CONTROLLER_NAME\n\n",[39,3178,3179,3183,3193,3197,3201,3209,3213,3218],{"__ignoreMap":231},[235,3180,3181],{"class":237,"line":238},[235,3182,3120],{"class":3119},[235,3184,3185,3187,3190],{"class":237,"line":249},[235,3186,1029],{"class":241},[235,3188,3189],{"class":245}," artisan",[235,3191,3192],{"class":245}," serve\n",[235,3194,3195],{"class":237,"line":259},[235,3196,263],{"emptyLinePlaceholder":262},[235,3198,3199],{"class":237,"line":266},[235,3200,3140],{"class":3119},[235,3202,3203,3205,3207],{"class":237,"line":275},[235,3204,1029],{"class":241},[235,3206,3189],{"class":245},[235,3208,3149],{"class":245},[235,3210,3211],{"class":237,"line":283},[235,3212,263],{"emptyLinePlaceholder":262},[235,3214,3215],{"class":237,"line":291},[235,3216,3217],{"class":3119},"# コントローラーのテンプレートを作成\n",[235,3219,3220,3222,3224,3227],{"class":237,"line":298},[235,3221,1029],{"class":241},[235,3223,3189],{"class":245},[235,3225,3226],{"class":245}," make:controller",[235,3228,3229],{"class":245}," CONTROLLER_NAME\n",[13,3231,3232,3233,3236,3237,3242],{},"以上の様になります。この ",[39,3234,3235],{},"python3 manage.py","で実行できる内容は",[197,3238,3241],{"href":3239,"rel":3240},"https:\u002F\u002Fdocs.djangoproject.com\u002Fja\u002F3.2\u002Fref\u002Fdjango-admin\u002F",[201],"こちらのドキュメント","で知ることができます。",[81,3244,3245],{"id":3245},"ディレクトリとファイルの構成",[13,3247,3248],{},"初期のファイル構成は以下の様になっています。",[226,3250,3252],{"className":228,"code":3251,"language":230,"meta":231,"style":231},"├── db.sqlite3\n├── djangodemo\n│   ├── __init__.py\n│   ├── asgi.py\n│   ├── settings.py\n│   ├── urls.py\n│   └── wsgi.py\n├── manage.py\n",[39,3253,3254,3262,3269,3280,3289,3298,3307,3317],{"__ignoreMap":231},[235,3255,3256,3259],{"class":237,"line":238},[235,3257,3258],{"class":241},"├──",[235,3260,3261],{"class":245}," db.sqlite3\n",[235,3263,3264,3266],{"class":237,"line":249},[235,3265,3258],{"class":241},[235,3267,3268],{"class":245}," djangodemo\n",[235,3270,3271,3274,3277],{"class":237,"line":259},[235,3272,3273],{"class":241},"│",[235,3275,3276],{"class":245},"   ├──",[235,3278,3279],{"class":245}," __init__.py\n",[235,3281,3282,3284,3286],{"class":237,"line":266},[235,3283,3273],{"class":241},[235,3285,3276],{"class":245},[235,3287,3288],{"class":245}," asgi.py\n",[235,3290,3291,3293,3295],{"class":237,"line":275},[235,3292,3273],{"class":241},[235,3294,3276],{"class":245},[235,3296,3297],{"class":245}," settings.py\n",[235,3299,3300,3302,3304],{"class":237,"line":283},[235,3301,3273],{"class":241},[235,3303,3276],{"class":245},[235,3305,3306],{"class":245}," urls.py\n",[235,3308,3309,3311,3314],{"class":237,"line":291},[235,3310,3273],{"class":241},[235,3312,3313],{"class":245},"   └──",[235,3315,3316],{"class":245}," wsgi.py\n",[235,3318,3319,3321],{"class":237,"line":298},[235,3320,3258],{"class":241},[235,3322,3323],{"class":245}," manage.py\n",[13,3325,3326,3329,3330,3332,3333,1209,3336,3339],{},[39,3327,3328],{},"djangodemo\u002F"," はDjangoのアプリを最初に作成した時に生成されるディレクトリです。",[39,3331,3328],{}," では特に ",[39,3334,3335],{},"settings.py",[39,3337,3338],{},"urls.py","が重要です。",[88,3341,3342],{"id":3342},"設定ファイル",[13,3344,3345,3347,3348,3351,3352,3355],{},[39,3346,3335],{}," はLaravelでいう",[39,3349,3350],{},"config\u002F","ディレクトリ配下のファイルたちを一つにまとめた様なものになっています。特に",[39,3353,3354],{},"config\u002Fapp.php","の記述が近いかもしれません。一部抜粋して解説します。",[226,3357,3361],{"className":3358,"code":3359,"filename":3335,"language":3360,"meta":231,"style":231},"language-python shiki shiki-themes material-theme-ocean","BASE_DIR = Path(__file__).resolve().parent.parent\n\nSECRET_KEY = 'hogehoge'\n\n# SECURITY WARNING: don't run with debug turned on in production!\n# Laravelのapp.debugと同じ\nDEBUG = True\n\n# Application definition\n# Djangoが利用可能なアプリ（モジュール）Laravelにはないかも。\nINSTALLED_APPS = [\n    'django.contrib.admin',\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.messages',\n    'django.contrib.staticfiles',\n]\n\n# laravel の app\u002FHttp\u002FKernel.php のmiddlewareみたいなもの\nMIDDLEWARE = [\n    'django.middleware.security.SecurityMiddleware',\n    'django.contrib.sessions.middleware.SessionMiddleware',\n    'django.middleware.common.CommonMiddleware',\n    'django.middleware.csrf.CsrfViewMiddleware',\n    'django.contrib.auth.middleware.AuthenticationMiddleware',\n    'django.contrib.messages.middleware.MessageMiddleware',\n    'django.middleware.clickjacking.XFrameOptionsMiddleware',\n]\n\n# Laravelのroutesみたいなもの。\nROOT_URLCONF = 'djangodemo.urls'\n\n# Laravelのビューテンプレートが resource\u002Fviewであることを決めている様なことと同じ。DjangoないのTemplateの読み込み先を定義している\nTEMPLATES = [\n    # ...\n]\n\nWSGI_APPLICATION = 'djangodemo.wsgi.application'\n\n# Laravelのconfig\u002Fdatabase.phpと同じ。使用するDBドライバやアクセス情報を記述。\nDATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.mysql',\n        'NAME': 'preform',\n        'USER': 'root',\n        'PASSWORD': 'rootroot',\n        'HOST': 'db',\n        'PORT': '3306',\n    }\n}\n\n# 静的ファイルを配置する箇所。Laravelのstorageディレクトリ を定義している様なもの。\nSTATIC_URL = '\u002Fstatic\u002F'\n\n","python",[39,3362,3363,3368,3372,3377,3381,3386,3391,3396,3400,3405,3410,3415,3420,3425,3430,3435,3440,3445,3449,3453,3458,3463,3468,3473,3478,3483,3488,3493,3498,3502,3506,3511,3516,3520,3525,3530,3535,3540,3545,3551,3556,3562,3568,3573,3579,3585,3591,3597,3603,3609,3614,3619,3624,3630],{"__ignoreMap":231},[235,3364,3365],{"class":237,"line":238},[235,3366,3367],{},"BASE_DIR = Path(__file__).resolve().parent.parent\n",[235,3369,3370],{"class":237,"line":249},[235,3371,263],{"emptyLinePlaceholder":262},[235,3373,3374],{"class":237,"line":259},[235,3375,3376],{},"SECRET_KEY = 'hogehoge'\n",[235,3378,3379],{"class":237,"line":266},[235,3380,263],{"emptyLinePlaceholder":262},[235,3382,3383],{"class":237,"line":275},[235,3384,3385],{},"# SECURITY WARNING: don't run with debug turned on in production!\n",[235,3387,3388],{"class":237,"line":283},[235,3389,3390],{},"# Laravelのapp.debugと同じ\n",[235,3392,3393],{"class":237,"line":291},[235,3394,3395],{},"DEBUG = True\n",[235,3397,3398],{"class":237,"line":298},[235,3399,263],{"emptyLinePlaceholder":262},[235,3401,3402],{"class":237,"line":380},[235,3403,3404],{},"# Application definition\n",[235,3406,3407],{"class":237,"line":465},[235,3408,3409],{},"# Djangoが利用可能なアプリ（モジュール）Laravelにはないかも。\n",[235,3411,3412],{"class":237,"line":590},[235,3413,3414],{},"INSTALLED_APPS = [\n",[235,3416,3417],{"class":237,"line":604},[235,3418,3419],{},"    'django.contrib.admin',\n",[235,3421,3422],{"class":237,"line":612},[235,3423,3424],{},"    'django.contrib.auth',\n",[235,3426,3427],{"class":237,"line":623},[235,3428,3429],{},"    'django.contrib.contenttypes',\n",[235,3431,3432],{"class":237,"line":634},[235,3433,3434],{},"    'django.contrib.sessions',\n",[235,3436,3437],{"class":237,"line":641},[235,3438,3439],{},"    'django.contrib.messages',\n",[235,3441,3442],{"class":237,"line":653},[235,3443,3444],{},"    'django.contrib.staticfiles',\n",[235,3446,3447],{"class":237,"line":661},[235,3448,1444],{},[235,3450,3451],{"class":237,"line":670},[235,3452,263],{"emptyLinePlaceholder":262},[235,3454,3455],{"class":237,"line":678},[235,3456,3457],{},"# laravel の app\u002FHttp\u002FKernel.php のmiddlewareみたいなもの\n",[235,3459,3460],{"class":237,"line":686},[235,3461,3462],{},"MIDDLEWARE = [\n",[235,3464,3465],{"class":237,"line":694},[235,3466,3467],{},"    'django.middleware.security.SecurityMiddleware',\n",[235,3469,3470],{"class":237,"line":702},[235,3471,3472],{},"    'django.contrib.sessions.middleware.SessionMiddleware',\n",[235,3474,3475],{"class":237,"line":712},[235,3476,3477],{},"    'django.middleware.common.CommonMiddleware',\n",[235,3479,3480],{"class":237,"line":723},[235,3481,3482],{},"    'django.middleware.csrf.CsrfViewMiddleware',\n",[235,3484,3485],{"class":237,"line":730},[235,3486,3487],{},"    'django.contrib.auth.middleware.AuthenticationMiddleware',\n",[235,3489,3490],{"class":237,"line":741},[235,3491,3492],{},"    'django.contrib.messages.middleware.MessageMiddleware',\n",[235,3494,3495],{"class":237,"line":752},[235,3496,3497],{},"    'django.middleware.clickjacking.XFrameOptionsMiddleware',\n",[235,3499,3500],{"class":237,"line":763},[235,3501,1444],{},[235,3503,3504],{"class":237,"line":774},[235,3505,263],{"emptyLinePlaceholder":262},[235,3507,3508],{"class":237,"line":785},[235,3509,3510],{},"# Laravelのroutesみたいなもの。\n",[235,3512,3513],{"class":237,"line":794},[235,3514,3515],{},"ROOT_URLCONF = 'djangodemo.urls'\n",[235,3517,3518],{"class":237,"line":806},[235,3519,263],{"emptyLinePlaceholder":262},[235,3521,3522],{"class":237,"line":815},[235,3523,3524],{},"# Laravelのビューテンプレートが resource\u002Fviewであることを決めている様なことと同じ。DjangoないのTemplateの読み込み先を定義している\n",[235,3526,3527],{"class":237,"line":823},[235,3528,3529],{},"TEMPLATES = [\n",[235,3531,3532],{"class":237,"line":833},[235,3533,3534],{},"    # ...\n",[235,3536,3538],{"class":237,"line":3537},37,[235,3539,1444],{},[235,3541,3543],{"class":237,"line":3542},38,[235,3544,263],{"emptyLinePlaceholder":262},[235,3546,3548],{"class":237,"line":3547},39,[235,3549,3550],{},"WSGI_APPLICATION = 'djangodemo.wsgi.application'\n",[235,3552,3554],{"class":237,"line":3553},40,[235,3555,263],{"emptyLinePlaceholder":262},[235,3557,3559],{"class":237,"line":3558},41,[235,3560,3561],{},"# Laravelのconfig\u002Fdatabase.phpと同じ。使用するDBドライバやアクセス情報を記述。\n",[235,3563,3565],{"class":237,"line":3564},42,[235,3566,3567],{},"DATABASES = {\n",[235,3569,3570],{"class":237,"line":4},[235,3571,3572],{},"    'default': {\n",[235,3574,3576],{"class":237,"line":3575},44,[235,3577,3578],{},"        'ENGINE': 'django.db.backends.mysql',\n",[235,3580,3582],{"class":237,"line":3581},45,[235,3583,3584],{},"        'NAME': 'preform',\n",[235,3586,3588],{"class":237,"line":3587},46,[235,3589,3590],{},"        'USER': 'root',\n",[235,3592,3594],{"class":237,"line":3593},47,[235,3595,3596],{},"        'PASSWORD': 'rootroot',\n",[235,3598,3600],{"class":237,"line":3599},48,[235,3601,3602],{},"        'HOST': 'db',\n",[235,3604,3606],{"class":237,"line":3605},49,[235,3607,3608],{},"        'PORT': '3306',\n",[235,3610,3612],{"class":237,"line":3611},50,[235,3613,2181],{},[235,3615,3617],{"class":237,"line":3616},51,[235,3618,1317],{},[235,3620,3622],{"class":237,"line":3621},52,[235,3623,263],{"emptyLinePlaceholder":262},[235,3625,3627],{"class":237,"line":3626},53,[235,3628,3629],{},"# 静的ファイルを配置する箇所。Laravelのstorageディレクトリ を定義している様なもの。\n",[235,3631,3633],{"class":237,"line":3632},54,[235,3634,3635],{},"STATIC_URL = '\u002Fstatic\u002F'\n",[88,3637,3638],{"id":3638},"ルーティング",[13,3640,3641,3642,3644,3645,3648,3649,3652,3653,3656],{},"次は",[39,3643,3338],{},"です。これはLaravelでいうところの ",[39,3646,3647],{},"routes\u002F","と内容的には一緒です。ここでHTTPリクエストに対する処理を結びつけています。Urlディスパッチャと言われています。Laravelでは",[39,3650,3651],{},"web.php","や",[39,3654,3655],{},"api.php","などいくらか分かれていますが、Djangoではデフォルトで一つです。詳細な記述は次回説明します。",[88,3658,3659],{"id":3659},"アプリ側のディレクトリ",[13,3661,3662,3663,3666],{},"次にアプリを作成します。Djangoは機能ごとにディレクトリを分割しアプリ(app)と呼んでいます。例としてユーザーのアカウント設定や認証を行う機能を作成するために、",[39,3664,3665],{},"account","というアプリを作成します。",[226,3668,3671],{"className":3669,"code":3670,"language":934},[932],"python3 manage.py startapp account\n",[39,3672,3670],{"__ignoreMap":231},[13,3674,3675,3676,3679],{},"ディレクトリ が一つ増えて、",[39,3677,3678],{},"account\u002F","というのが作成されたはずです。アプリ内には初期では以下の通りテンプレートが作成されます。",[226,3681,3684],{"className":3682,"code":3683,"language":934},[932],"├── account\n│   ├── __init__.py\n│   ├── admin.py\n│   ├── apps.py\n│   ├── migrations\n│   │   └── __init__.py\n│   ├── models.py\n│   ├── tests.py\n│   └── views.py\n├── db.sqlite3\n├── djangodemo\n├── manage.py\n",[39,3685,3683],{"__ignoreMap":231},[13,3687,3688,3689,3692,3693,3695],{},"Laravelは",[39,3690,3691],{},"app\u002F","配下にコントローラーやモデル、ジョブなどのクラスファイルを定義します。独立した機能であっても",[39,3694,3691],{},"配下に配置してクラス名などで判別する感じです。",[13,3697,3698,3699,3703],{},"しかしDjangoは",[3700,3701,3702],"strong",{},"機能ごとにディレクトリ を作成し、その機能に関連するモデル、ビュー、テストの設定を記述","します。ここがLaravelとすこし違うところです。",[13,3705,3706,3707,3710,3711,3714],{},"アプリを",[39,3708,3709],{},"setting.py","の",[39,3712,3713],{},"INSTALLED_APPS","に記述することで、",[226,3716,3718],{"className":3358,"code":3717,"language":3360,"meta":231,"style":231},"from account.model import Account\n\n# account\u002Fmodel.py のAccountクラスを使用する\n",[39,3719,3720,3725,3729],{"__ignoreMap":231},[235,3721,3722],{"class":237,"line":238},[235,3723,3724],{},"from account.model import Account\n",[235,3726,3727],{"class":237,"line":249},[235,3728,263],{"emptyLinePlaceholder":262},[235,3730,3731],{"class":237,"line":259},[235,3732,3733],{},"# account\u002Fmodel.py のAccountクラスを使用する\n",[13,3735,3736,3737,3739],{},"などそのアプリ内機能をモジュールとして使用できます。Laravel（PHP）風に解説すると、適切な名前空間を定義して任意のファイルで",[39,3738,1832],{},"する感じです。",[226,3741,3743],{"className":1026,"code":3742,"language":1029,"meta":231,"style":231},"use App\\Models\\Account\n",[39,3744,3745],{"__ignoreMap":231},[235,3746,3747],{"class":237,"line":238},[235,3748,3742],{},[13,3750,3751],{},"それぞれのファイルを説明します。",[17,3753,3754,3760,3769,3778,3787,3793],{},[20,3755,3756,3759],{},[39,3757,3758],{},"admin.py",":Djangoが提供する管理者画面でモデルの内容をどう表記するかを定義します。",[20,3761,3762,3765,3766,3768],{},[39,3763,3764],{},"apps.py",":アプリの設定ファイル。アプリの名前やデフォルトのプライマリーキーなどを設定でき、",[39,3767,3713],{},"に必要",[20,3770,3771,3774,3775],{},[39,3772,3773],{},"models.py",": アプリのモデルファイル。テーブルや使用するフィールドの定義などを行う。Laravelでいう",[39,3776,3777],{},"app\u002Fmodels",[20,3779,3780,3783,3784],{},[39,3781,3782],{},"tets.py",": アプリのテストファイル。テストコードを記述する。Laravelでいう",[39,3785,3786],{},"tests\u002F",[20,3788,3789,3792],{},[39,3790,3791],{},"views.py",": アプリのビューファイル。DjangoではビューはLaravelでいうControllerみたいな働きをする。",[20,3794,3795,3798,3799,3802],{},[39,3796,3797],{},"migrations\u002F",": DBに対する変更、マイグレーションファイルが格納されます。Laravelでいう、",[39,3800,3801],{},"database\u002Fmigrations","です。",[13,3804,3805,3806,3809],{},"のこっている ",[39,3807,3808],{},"__init__.py","ですがこれはpythonがディレクトリ をパッケージとして認識して、importできる様にするために必要なファイルです。python2ではこのファイルがないとimportが動作しません。python3からは不要ですが、後方互換性のために作っておいて損はありません。",[226,3811,3813],{"className":3358,"code":3812,"language":3360,"meta":231,"style":231},"from account.models\n\"\"\"\naccountディレクトリ（パッケージ）のmodels.py（モジュール）を読み込むということが,\n__init__.pyがあるとできる。\n\"\"\"\n",[39,3814,3815,3820,3825,3830,3835],{"__ignoreMap":231},[235,3816,3817],{"class":237,"line":238},[235,3818,3819],{},"from account.models\n",[235,3821,3822],{"class":237,"line":249},[235,3823,3824],{},"\"\"\"\n",[235,3826,3827],{"class":237,"line":259},[235,3828,3829],{},"accountディレクトリ（パッケージ）のmodels.py（モジュール）を読み込むということが,\n",[235,3831,3832],{"class":237,"line":266},[235,3833,3834],{},"__init__.pyがあるとできる。\n",[235,3836,3837],{"class":237,"line":275},[235,3838,3824],{},[74,3840,3841],{"id":3841},"今回はとりあえずここまで",[13,3843,3844],{},"ひとまずこの回ではディレクトリやファイルの説明までとしておきます。次回はユーザーモデルを使用した認証の実装とLaravelと比較したCRUDの一部（記事の作成）を実装します。",[2399,3846,3847],{},"html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}",{"title":231,"searchDepth":259,"depth":259,"links":3849},[3850,3854,3859,3867],{"id":192,"depth":249,"text":192,"children":3851},[3852,3853],{"id":2578,"depth":259,"text":316},{"id":877,"depth":259,"text":877},{"id":3014,"depth":249,"text":3014,"children":3855},[3856,3857,3858],{"id":90,"depth":266,"text":90},{"id":124,"depth":266,"text":124},{"id":164,"depth":266,"text":164},{"id":3091,"depth":249,"text":3092,"children":3860},[3861,3862],{"id":3098,"depth":259,"text":3098},{"id":3245,"depth":259,"text":3245,"children":3863},[3864,3865,3866],{"id":3342,"depth":266,"text":3342},{"id":3638,"depth":266,"text":3638},{"id":3659,"depth":266,"text":3659},{"id":3841,"depth":249,"text":3841},[2427],"2022-02-12",{},"\u002Fseries\u002Flaravel-to-django-1",{"title":2443,"description":2429},"laravel_to_django","Laravel使いがDjangoでwebアプリを作るよ","series\u002Flaravel-to-django-1",[3877,3360,971,1029],"django","laralve_to_django\u002Fthumbnail.png","k4TYlI4xXfHM5YMh4HtklCzEfD1cyqgLf2FCDeypoBY",{"id":3881,"title":3882,"body":3883,"category":7947,"createdAt":7948,"description":7949,"extension":2430,"index":259,"meta":7950,"navigation":262,"path":7951,"publish":262,"seo":7952,"series":7953,"seriesTitle":7954,"stem":7955,"tag":7956,"thumbnail":7958,"updatedAt":2439,"__hash__":7959},"series\u002Fseries\u002Fwell-study-webpack-3.md","ちゃんと理解するWebpack5。３：HTMLのバンドルとPUGでのページ作成",{"type":10,"value":3884,"toc":7931},[3885,3893,3896,3904,3907,3911,3927,3930,3934,3937,3943,3959,3962,3972,3978,3981,3988,4228,4231,4238,4738,4745,4776,4786,5011,5020,5031,5038,5041,5049,5110,5116,5153,5161,5319,5322,5377,5390,5394,5400,5403,5406,5409,5500,5507,5613,5616,5619,5625,5631,5652,5667,5670,5673,5679,5684,5690,5947,5950,6464,6467,6531,6543,6546,6549,6559,6588,6591,6595,6601,7928],[13,3886,3887,3888,3892],{},"こんにちはjunです。前回の記事",[197,3889,3891],{"href":3890},"\u002Fseries\u002Fwell-study-webpack\u002F2","ちゃんと理解するWebpack5。２：Babel、画像の処理と複数バンドル","の続きの記事です。前回は画像のバンドル、Bableのトランスコンパイル、そして複数バンドルを行いました。今回は残りのHTMLの取り扱い方と、テンプレートエンジンと呼ばれるPUGを用いてHTMLでページをガンガン作成していこうと思います。",[13,3894,3895],{},"シチュエーションとしては、",[17,3897,3898,3901],{},[20,3899,3900],{},"サイト制作で上がってきたデザインからHTML・CSS・JSのテンプレートファイルを作る。",[20,3902,3903],{},"モックとしてサービスのweb部分を作ってみる",[13,3905,3906],{},"といった感じです。とりあえず「デザイン通りに見た目と動きつくってちょ！」というような依頼が来たと思ってください。",[74,3908,3910],{"id":3909},"webpakcでhtmlを扱うには","webpakcでHTMLを扱うには",[13,3912,3913,3914,3918,3919,3922,3923,3926],{},"webpackには「html-loader」というhtmlファイルを扱うloaderがあります。",[197,3915,3917],{"href":3916},"\u002Fseries\u002Fwell-study-webpack\u002F1","ちゃんと理解するWebpack5。１","では最初ということもあり、",[39,3920,3921],{},"dist","に直接置いていましたが、ローダーを使用することでHTMLも",[39,3924,3925],{},"src","配下に置いてバンドルできます。複数対応ももちろん可能です。",[13,3928,3929],{},"今回はまず素のHTMLを扱う方法とテンプレートエンジンという効率的にHTMLを生成できるpugを用いた2つのバンドル方法を今回はお伝えします。",[74,3931,3933],{"id":3932},"単純htmlファイルをバンドルする","単純HTMLファイルをバンドルする",[13,3935,3936],{},"前回の構成に加えて",[226,3938,3941],{"className":3939,"code":3940,"language":934},[932],".\n├── dist\n├── package-lock.json\n├── package.json\n├── src\n│   ├── imgs\n│   ├── html \u002F\u002FNEW!!\n│   │   ├── index.html \u002F\u002FNEW!!\n│   │   └── detail.html \u002F\u002FNEW!!\n│   ├── js\n│   │   ├── functions.js\n│   │   └── main.js\n│   └── sass\n│       ├── compnent.scss\n│       ├── style.scss\n│       └── variable.scss\n├── node_modules\n└── webpack.config.js\n",[39,3942,3940],{"__ignoreMap":231},[13,3944,3945,3948,3949,1209,3952,3955,3956,3958],{},[39,3946,3947],{},"html","というディレクトリを作成し、バンドル対象の",[39,3950,3951],{},"index.html",[39,3953,3954],{},"detail.html","を作成しました。目標はこの２つのファイルが",[39,3957,3921],{},"配下に配置されることです。",[81,3960,3961],{"id":3961},"html扱いに必要なloaderとpluginを入れる",[13,3963,3964,3965,1209,3968,3971],{},"最初にHTMLファイルを扱うために必要な",[39,3966,3967],{},"html-loader",[39,3969,3970],{},"HtmlWebpackPlugin","をインストールします。",[226,3973,3976],{"className":3974,"code":3975,"language":934},[932],"npm install -D html-loader html-webpack-plugin\n",[39,3977,3975],{"__ignoreMap":231},[81,3979,3980],{"id":3980},"ruleとloaderを追加",[13,3982,3983,3984,3987],{},"そしてwebpack.config.jsにhtmlに関する。記述を追加します。まずは",[39,3985,3986],{},"rules","にhtmlファイルのルールを追加します。",[226,3989,3993],{"className":3990,"code":3991,"filename":2046,"language":3992,"meta":231,"style":231},"language-javascript shiki shiki-themes material-theme-ocean","\n\u002F\u002F rulesの配列は後で\nlet rules = [\n    \u002F\u002F ... \n    \u002F\u002F 追加↓\n    {\n        test: \u002F\\.(html)$\u002F,\n        use: {\n            loader: 'html-loader',\n        }\n    },\n    \u002F\u002F ...\n]\n\nconst buildDefault = = {\n    entry: '.\u002Fsrc\u002Fjs\u002Fmain.js',\n  \n    mode:\"development\",\n    \n    module: {\n        rules: rules\n    },\n\n    rules:rules,\n    \u002F\u002F ...\n}\n\u002F\u002F...\n\nmodule.exports = buildDefault;\n","javascript",[39,3994,3995,3999,4004,4016,4021,4026,4031,4058,4067,4082,4087,4092,4097,4101,4105,4119,4135,4140,4156,4161,4170,4180,4184,4188,4199,4203,4207,4212,4216],{"__ignoreMap":231},[235,3996,3997],{"class":237,"line":238},[235,3998,263],{"emptyLinePlaceholder":262},[235,4000,4001],{"class":237,"line":249},[235,4002,4003],{"class":3119},"\u002F\u002F rulesの配列は後で\n",[235,4005,4006,4009,4012,4014],{"class":237,"line":259},[235,4007,4008],{"class":1375},"let",[235,4010,4011],{"class":519}," rules ",[235,4013,1382],{"class":499},[235,4015,1385],{"class":519},[235,4017,4018],{"class":237,"line":266},[235,4019,4020],{"class":3119},"    \u002F\u002F ... \n",[235,4022,4023],{"class":237,"line":275},[235,4024,4025],{"class":3119},"    \u002F\u002F 追加↓\n",[235,4027,4028],{"class":237,"line":283},[235,4029,4030],{"class":499},"    {\n",[235,4032,4033,4036,4038,4041,4044,4046,4048,4050,4053,4056],{"class":237,"line":291},[235,4034,4035],{"class":495},"        test",[235,4037,500],{"class":499},[235,4039,4040],{"class":499}," \u002F",[235,4042,4043],{"class":519},"\\.",[235,4045,1705],{"class":499},[235,4047,3947],{"class":245},[235,4049,1715],{"class":499},[235,4051,4052],{"class":1269},"$",[235,4054,4055],{"class":499},"\u002F",[235,4057,1984],{"class":499},[235,4059,4060,4063,4065],{"class":237,"line":298},[235,4061,4062],{"class":495},"        use",[235,4064,500],{"class":499},[235,4066,1276],{"class":499},[235,4068,4069,4072,4074,4076,4078,4080],{"class":237,"line":380},[235,4070,4071],{"class":495},"            loader",[235,4073,500],{"class":499},[235,4075,503],{"class":499},[235,4077,3967],{"class":245},[235,4079,1345],{"class":499},[235,4081,1984],{"class":499},[235,4083,4084],{"class":237,"line":465},[235,4085,4086],{"class":499},"        }\n",[235,4088,4089],{"class":237,"line":590},[235,4090,4091],{"class":499},"    },\n",[235,4093,4094],{"class":237,"line":604},[235,4095,4096],{"class":3119},"    \u002F\u002F ...\n",[235,4098,4099],{"class":237,"line":612},[235,4100,1444],{"class":519},[235,4102,4103],{"class":237,"line":623},[235,4104,263],{"emptyLinePlaceholder":262},[235,4106,4107,4109,4112,4114,4117],{"class":237,"line":634},[235,4108,1376],{"class":1375},[235,4110,4111],{"class":519}," buildDefault ",[235,4113,1382],{"class":499},[235,4115,4116],{"class":499}," =",[235,4118,1276],{"class":499},[235,4120,4121,4124,4126,4128,4131,4133],{"class":237,"line":641},[235,4122,4123],{"class":495},"    entry",[235,4125,500],{"class":499},[235,4127,503],{"class":499},[235,4129,4130],{"class":245},".\u002Fsrc\u002Fjs\u002Fmain.js",[235,4132,1345],{"class":499},[235,4134,1984],{"class":499},[235,4136,4137],{"class":237,"line":653},[235,4138,4139],{"class":519},"  \n",[235,4141,4142,4145,4147,4149,4152,4154],{"class":237,"line":661},[235,4143,4144],{"class":495},"    mode",[235,4146,500],{"class":499},[235,4148,1517],{"class":499},[235,4150,4151],{"class":245},"development",[235,4153,1517],{"class":499},[235,4155,1984],{"class":499},[235,4157,4158],{"class":237,"line":670},[235,4159,4160],{"class":519},"    \n",[235,4162,4163,4166,4168],{"class":237,"line":678},[235,4164,4165],{"class":495},"    module",[235,4167,500],{"class":499},[235,4169,1276],{"class":499},[235,4171,4172,4175,4177],{"class":237,"line":686},[235,4173,4174],{"class":495},"        rules",[235,4176,500],{"class":499},[235,4178,4179],{"class":519}," rules\n",[235,4181,4182],{"class":237,"line":694},[235,4183,4091],{"class":499},[235,4185,4186],{"class":237,"line":702},[235,4187,263],{"emptyLinePlaceholder":262},[235,4189,4190,4193,4195,4197],{"class":237,"line":712},[235,4191,4192],{"class":495},"    rules",[235,4194,500],{"class":499},[235,4196,3986],{"class":519},[235,4198,1984],{"class":499},[235,4200,4201],{"class":237,"line":723},[235,4202,4096],{"class":3119},[235,4204,4205],{"class":237,"line":730},[235,4206,1317],{"class":499},[235,4208,4209],{"class":237,"line":741},[235,4210,4211],{"class":3119},"\u002F\u002F...\n",[235,4213,4214],{"class":237,"line":752},[235,4215,263],{"emptyLinePlaceholder":262},[235,4217,4218,4221,4223,4226],{"class":237,"line":763},[235,4219,4220],{"class":499},"module.exports",[235,4222,4116],{"class":499},[235,4224,4225],{"class":519}," buildDefault",[235,4227,1348],{"class":499},[81,4229,4230],{"id":4230},"html-webpack-pluginの設定",[13,4232,4233,4234,4237],{},"とりあえずこれでwebpackはhtmlファイルを扱えるようになりました。次はentryでjsファイルを指定していたように、バンドル対象のhtmlをwebpackに読み込ませるために",[39,4235,4236],{},"html-webpack-plugin","を使用します。",[226,4239,4241],{"className":3990,"code":4240,"filename":2046,"language":3992,"meta":231,"style":231},"\u002F\u002F ファイル冒頭\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst path = require('path');\n\n\u002F\u002F この２つを追加\nconst globule = require('globule');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\n\nlet rules = [\n    \u002F\u002F 省略... \n]\n\nconst buildDefault = = {\n    entry: '.\u002Fsrc\u002Fjs\u002Fmain.js',\n  \n    mode:\"development\",\n    \n    module: {\n        rules: rules\n    },\n\n    rules:rules,\n    \u002F\u002F 以下略...\n}\n\n\u002F\u002F これらを追記\nconst htmlFiles = globule.find('src\u002Fhtml\u002F*.html');\n\nhtmlFiles.forEach((htmlsrc) => {\n    const htmlname = htmlsrc.split('\u002F').slice(-1)[0];\n\n    buildDefault.plugins.push(\n      new HtmlWebpackPlugin({\n        filename: `${path.resolve(__dirname, 'dist')}\u002F${htmlname}`,\n        inject:'body',\n        template: htmlsrc,\n        minify: false\n      })\n    )\n});\n\nmodule.exports = buildDefault;\n",[39,4242,4243,4248,4272,4294,4298,4303,4327,4350,4354,4364,4369,4373,4377,4389,4403,4407,4421,4425,4433,4441,4445,4449,4459,4464,4468,4472,4477,4507,4511,4536,4588,4592,4610,4622,4666,4682,4693,4704,4711,4716,4724,4728],{"__ignoreMap":231},[235,4244,4245],{"class":237,"line":238},[235,4246,4247],{"class":3119},"\u002F\u002F ファイル冒頭\n",[235,4249,4250,4252,4255,4257,4259,4261,4263,4266,4268,4270],{"class":237,"line":249},[235,4251,1376],{"class":1375},[235,4253,4254],{"class":519}," MiniCssExtractPlugin ",[235,4256,1382],{"class":499},[235,4258,1702],{"class":252},[235,4260,1705],{"class":519},[235,4262,1345],{"class":499},[235,4264,4265],{"class":245},"mini-css-extract-plugin",[235,4267,1345],{"class":499},[235,4269,1715],{"class":519},[235,4271,1348],{"class":499},[235,4273,4274,4276,4278,4280,4282,4284,4286,4288,4290,4292],{"class":237,"line":259},[235,4275,1376],{"class":1375},[235,4277,2087],{"class":519},[235,4279,1382],{"class":499},[235,4281,1702],{"class":252},[235,4283,1705],{"class":519},[235,4285,1345],{"class":499},[235,4287,2098],{"class":245},[235,4289,1345],{"class":499},[235,4291,1715],{"class":519},[235,4293,1348],{"class":499},[235,4295,4296],{"class":237,"line":266},[235,4297,263],{"emptyLinePlaceholder":262},[235,4299,4300],{"class":237,"line":275},[235,4301,4302],{"class":3119},"\u002F\u002F この２つを追加\n",[235,4304,4305,4307,4310,4312,4314,4316,4318,4321,4323,4325],{"class":237,"line":283},[235,4306,1376],{"class":1375},[235,4308,4309],{"class":519}," globule ",[235,4311,1382],{"class":499},[235,4313,1702],{"class":252},[235,4315,1705],{"class":519},[235,4317,1345],{"class":499},[235,4319,4320],{"class":245},"globule",[235,4322,1345],{"class":499},[235,4324,1715],{"class":519},[235,4326,1348],{"class":499},[235,4328,4329,4331,4334,4336,4338,4340,4342,4344,4346,4348],{"class":237,"line":291},[235,4330,1376],{"class":1375},[235,4332,4333],{"class":519}," HtmlWebpackPlugin ",[235,4335,1382],{"class":499},[235,4337,1702],{"class":252},[235,4339,1705],{"class":519},[235,4341,1345],{"class":499},[235,4343,4236],{"class":245},[235,4345,1345],{"class":499},[235,4347,1715],{"class":519},[235,4349,1348],{"class":499},[235,4351,4352],{"class":237,"line":298},[235,4353,263],{"emptyLinePlaceholder":262},[235,4355,4356,4358,4360,4362],{"class":237,"line":380},[235,4357,4008],{"class":1375},[235,4359,4011],{"class":519},[235,4361,1382],{"class":499},[235,4363,1385],{"class":519},[235,4365,4366],{"class":237,"line":465},[235,4367,4368],{"class":3119},"    \u002F\u002F 省略... \n",[235,4370,4371],{"class":237,"line":590},[235,4372,1444],{"class":519},[235,4374,4375],{"class":237,"line":604},[235,4376,263],{"emptyLinePlaceholder":262},[235,4378,4379,4381,4383,4385,4387],{"class":237,"line":612},[235,4380,1376],{"class":1375},[235,4382,4111],{"class":519},[235,4384,1382],{"class":499},[235,4386,4116],{"class":499},[235,4388,1276],{"class":499},[235,4390,4391,4393,4395,4397,4399,4401],{"class":237,"line":623},[235,4392,4123],{"class":495},[235,4394,500],{"class":499},[235,4396,503],{"class":499},[235,4398,4130],{"class":245},[235,4400,1345],{"class":499},[235,4402,1984],{"class":499},[235,4404,4405],{"class":237,"line":634},[235,4406,4139],{"class":519},[235,4408,4409,4411,4413,4415,4417,4419],{"class":237,"line":641},[235,4410,4144],{"class":495},[235,4412,500],{"class":499},[235,4414,1517],{"class":499},[235,4416,4151],{"class":245},[235,4418,1517],{"class":499},[235,4420,1984],{"class":499},[235,4422,4423],{"class":237,"line":653},[235,4424,4160],{"class":519},[235,4426,4427,4429,4431],{"class":237,"line":661},[235,4428,4165],{"class":495},[235,4430,500],{"class":499},[235,4432,1276],{"class":499},[235,4434,4435,4437,4439],{"class":237,"line":670},[235,4436,4174],{"class":495},[235,4438,500],{"class":499},[235,4440,4179],{"class":519},[235,4442,4443],{"class":237,"line":678},[235,4444,4091],{"class":499},[235,4446,4447],{"class":237,"line":686},[235,4448,263],{"emptyLinePlaceholder":262},[235,4450,4451,4453,4455,4457],{"class":237,"line":694},[235,4452,4192],{"class":495},[235,4454,500],{"class":499},[235,4456,3986],{"class":519},[235,4458,1984],{"class":499},[235,4460,4461],{"class":237,"line":702},[235,4462,4463],{"class":3119},"    \u002F\u002F 以下略...\n",[235,4465,4466],{"class":237,"line":712},[235,4467,1317],{"class":499},[235,4469,4470],{"class":237,"line":723},[235,4471,263],{"emptyLinePlaceholder":262},[235,4473,4474],{"class":237,"line":730},[235,4475,4476],{"class":3119},"\u002F\u002F これらを追記\n",[235,4478,4479,4481,4484,4486,4489,4491,4494,4496,4498,4501,4503,4505],{"class":237,"line":741},[235,4480,1376],{"class":1375},[235,4482,4483],{"class":519}," htmlFiles ",[235,4485,1382],{"class":499},[235,4487,4488],{"class":519}," globule",[235,4490,1694],{"class":499},[235,4492,4493],{"class":252},"find",[235,4495,1705],{"class":519},[235,4497,1345],{"class":499},[235,4499,4500],{"class":245},"src\u002Fhtml\u002F*.html",[235,4502,1345],{"class":499},[235,4504,1715],{"class":519},[235,4506,1348],{"class":499},[235,4508,4509],{"class":237,"line":752},[235,4510,263],{"emptyLinePlaceholder":262},[235,4512,4513,4516,4518,4521,4523,4525,4529,4531,4534],{"class":237,"line":763},[235,4514,4515],{"class":519},"htmlFiles",[235,4517,1694],{"class":499},[235,4519,4520],{"class":252},"forEach",[235,4522,1705],{"class":519},[235,4524,1705],{"class":499},[235,4526,4528],{"class":4527},"s7ZW3","htmlsrc",[235,4530,1715],{"class":499},[235,4532,4533],{"class":1375}," =>",[235,4535,1276],{"class":499},[235,4537,4538,4541,4544,4546,4549,4551,4554,4556,4558,4560,4562,4564,4566,4569,4571,4574,4577,4580,4583,4586],{"class":237,"line":774},[235,4539,4540],{"class":1375},"    const",[235,4542,4543],{"class":519}," htmlname",[235,4545,4116],{"class":499},[235,4547,4548],{"class":519}," htmlsrc",[235,4550,1694],{"class":499},[235,4552,4553],{"class":252},"split",[235,4555,1705],{"class":495},[235,4557,1345],{"class":499},[235,4559,4055],{"class":245},[235,4561,1345],{"class":499},[235,4563,1715],{"class":495},[235,4565,1694],{"class":499},[235,4567,4568],{"class":252},"slice",[235,4570,1705],{"class":495},[235,4572,4573],{"class":499},"-",[235,4575,4576],{"class":2836},"1",[235,4578,4579],{"class":495},")[",[235,4581,4582],{"class":2836},"0",[235,4584,4585],{"class":495},"]",[235,4587,1348],{"class":499},[235,4589,4590],{"class":237,"line":785},[235,4591,263],{"emptyLinePlaceholder":262},[235,4593,4594,4597,4599,4602,4604,4607],{"class":237,"line":794},[235,4595,4596],{"class":519},"    buildDefault",[235,4598,1694],{"class":499},[235,4600,4601],{"class":519},"plugins",[235,4603,1694],{"class":499},[235,4605,4606],{"class":252},"push",[235,4608,4609],{"class":495},"(\n",[235,4611,4612,4615,4618,4620],{"class":237,"line":806},[235,4613,4614],{"class":499},"      new",[235,4616,4617],{"class":252}," HtmlWebpackPlugin",[235,4619,1705],{"class":495},[235,4621,1976],{"class":499},[235,4623,4624,4627,4629,4632,4634,4636,4638,4641,4643,4645,4647,4649,4651,4653,4655,4658,4661,4664],{"class":237,"line":815},[235,4625,4626],{"class":495},"        filename",[235,4628,500],{"class":499},[235,4630,4631],{"class":499}," `${",[235,4633,2098],{"class":519},[235,4635,1694],{"class":499},[235,4637,2158],{"class":252},[235,4639,4640],{"class":519},"(__dirname",[235,4642,1404],{"class":499},[235,4644,503],{"class":499},[235,4646,3921],{"class":245},[235,4648,1345],{"class":499},[235,4650,1715],{"class":519},[235,4652,1950],{"class":499},[235,4654,4055],{"class":245},[235,4656,4657],{"class":499},"${",[235,4659,4660],{"class":519},"htmlname",[235,4662,4663],{"class":499},"}`",[235,4665,1984],{"class":499},[235,4667,4668,4671,4673,4675,4678,4680],{"class":237,"line":823},[235,4669,4670],{"class":495},"        inject",[235,4672,500],{"class":499},[235,4674,1345],{"class":499},[235,4676,4677],{"class":245},"body",[235,4679,1345],{"class":499},[235,4681,1984],{"class":499},[235,4683,4684,4687,4689,4691],{"class":237,"line":833},[235,4685,4686],{"class":495},"        template",[235,4688,500],{"class":499},[235,4690,4548],{"class":519},[235,4692,1984],{"class":499},[235,4694,4695,4698,4700],{"class":237,"line":3537},[235,4696,4697],{"class":495},"        minify",[235,4699,500],{"class":499},[235,4701,4703],{"class":4702},"sbqyR"," false\n",[235,4705,4706,4709],{"class":237,"line":3542},[235,4707,4708],{"class":499},"      }",[235,4710,1953],{"class":495},[235,4712,4713],{"class":237,"line":3547},[235,4714,4715],{"class":495},"    )\n",[235,4717,4718,4720,4722],{"class":237,"line":3553},[235,4719,1950],{"class":499},[235,4721,1715],{"class":519},[235,4723,1348],{"class":499},[235,4725,4726],{"class":237,"line":3558},[235,4727,263],{"emptyLinePlaceholder":262},[235,4729,4730,4732,4734,4736],{"class":237,"line":3564},[235,4731,4220],{"class":499},[235,4733,4116],{"class":499},[235,4735,4225],{"class":519},[235,4737,1348],{"class":499},[13,4739,4740,4741,4744],{},"詳細の解説をします。まず最初に必要なプラグインとnode.jsのモジュールをインポートします。そして以下の記述は",[39,4742,4743],{},"src\u002Fhtml","配下にあるhtmlファイルを全て取得する処理です。",[226,4746,4748],{"className":3990,"code":4747,"language":3992,"meta":231,"style":231},"const htmlFiles = globule.find('src\u002Fhtml\u002F*.html');\n",[39,4749,4750],{"__ignoreMap":231},[235,4751,4752,4754,4756,4758,4760,4762,4764,4766,4768,4770,4772,4774],{"class":237,"line":238},[235,4753,1376],{"class":1375},[235,4755,4483],{"class":519},[235,4757,1382],{"class":499},[235,4759,4488],{"class":519},[235,4761,1694],{"class":499},[235,4763,4493],{"class":252},[235,4765,1705],{"class":519},[235,4767,1345],{"class":499},[235,4769,4500],{"class":245},[235,4771,1345],{"class":499},[235,4773,1715],{"class":519},[235,4775,1348],{"class":499},[13,4777,4778,4779,4781,4782,4785],{},"配列でhtmlファイルのパスが戻ってきますので、それらを",[39,4780,3970],{},"にファイル分だけ",[39,4783,4784],{},"new","します。",[226,4787,4789],{"className":3990,"code":4788,"language":3992,"meta":231,"style":231},"htmlFiles.forEach((htmlsrc) => {\n    \u002F\u002F ファイル名を取得 src\u002Fhtml\u002Findex.html → index.html\n    const htmlname = htmlsrc.split('\u002F').slice(-1)[0];\n\n    \u002F\u002F webpackの設定にある、pluginsに以下のプラグインインスタンスを入れる。\n    buildDefault.plugins.push(\n      new HtmlWebpackPlugin({\n        \u002F\u002F distのファイル名。今回はsrcと同じ。\n        filename: `${path.resolve(__dirname, 'dist')}\u002F${htmlname}`,\n\n        \u002F\u002F 自動的にバンドル対象のjs\b(main.js)とcss(style.css)を入れる。お節介ならfalseにする。\n        inject:'body',\n\n        \u002F\u002F 対象のhtmlファイル\n        template: htmlsrc,\n\n        \u002F\u002F 圧縮するかどうか。defaultはtrue\n        minify: false\n      })\n    )\n});\n",[39,4790,4791,4811,4816,4858,4862,4867,4881,4891,4896,4934,4938,4943,4957,4961,4966,4976,4980,4985,4993,4999,5003],{"__ignoreMap":231},[235,4792,4793,4795,4797,4799,4801,4803,4805,4807,4809],{"class":237,"line":238},[235,4794,4515],{"class":519},[235,4796,1694],{"class":499},[235,4798,4520],{"class":252},[235,4800,1705],{"class":519},[235,4802,1705],{"class":499},[235,4804,4528],{"class":4527},[235,4806,1715],{"class":499},[235,4808,4533],{"class":1375},[235,4810,1276],{"class":499},[235,4812,4813],{"class":237,"line":249},[235,4814,4815],{"class":3119},"    \u002F\u002F ファイル名を取得 src\u002Fhtml\u002Findex.html → index.html\n",[235,4817,4818,4820,4822,4824,4826,4828,4830,4832,4834,4836,4838,4840,4842,4844,4846,4848,4850,4852,4854,4856],{"class":237,"line":259},[235,4819,4540],{"class":1375},[235,4821,4543],{"class":519},[235,4823,4116],{"class":499},[235,4825,4548],{"class":519},[235,4827,1694],{"class":499},[235,4829,4553],{"class":252},[235,4831,1705],{"class":495},[235,4833,1345],{"class":499},[235,4835,4055],{"class":245},[235,4837,1345],{"class":499},[235,4839,1715],{"class":495},[235,4841,1694],{"class":499},[235,4843,4568],{"class":252},[235,4845,1705],{"class":495},[235,4847,4573],{"class":499},[235,4849,4576],{"class":2836},[235,4851,4579],{"class":495},[235,4853,4582],{"class":2836},[235,4855,4585],{"class":495},[235,4857,1348],{"class":499},[235,4859,4860],{"class":237,"line":266},[235,4861,263],{"emptyLinePlaceholder":262},[235,4863,4864],{"class":237,"line":275},[235,4865,4866],{"class":3119},"    \u002F\u002F webpackの設定にある、pluginsに以下のプラグインインスタンスを入れる。\n",[235,4868,4869,4871,4873,4875,4877,4879],{"class":237,"line":283},[235,4870,4596],{"class":519},[235,4872,1694],{"class":499},[235,4874,4601],{"class":519},[235,4876,1694],{"class":499},[235,4878,4606],{"class":252},[235,4880,4609],{"class":495},[235,4882,4883,4885,4887,4889],{"class":237,"line":291},[235,4884,4614],{"class":499},[235,4886,4617],{"class":252},[235,4888,1705],{"class":495},[235,4890,1976],{"class":499},[235,4892,4893],{"class":237,"line":298},[235,4894,4895],{"class":3119},"        \u002F\u002F distのファイル名。今回はsrcと同じ。\n",[235,4897,4898,4900,4902,4904,4906,4908,4910,4912,4914,4916,4918,4920,4922,4924,4926,4928,4930,4932],{"class":237,"line":380},[235,4899,4626],{"class":495},[235,4901,500],{"class":499},[235,4903,4631],{"class":499},[235,4905,2098],{"class":519},[235,4907,1694],{"class":499},[235,4909,2158],{"class":252},[235,4911,4640],{"class":519},[235,4913,1404],{"class":499},[235,4915,503],{"class":499},[235,4917,3921],{"class":245},[235,4919,1345],{"class":499},[235,4921,1715],{"class":519},[235,4923,1950],{"class":499},[235,4925,4055],{"class":245},[235,4927,4657],{"class":499},[235,4929,4660],{"class":519},[235,4931,4663],{"class":499},[235,4933,1984],{"class":499},[235,4935,4936],{"class":237,"line":465},[235,4937,263],{"emptyLinePlaceholder":262},[235,4939,4940],{"class":237,"line":590},[235,4941,4942],{"class":3119},"        \u002F\u002F 自動的にバンドル対象のjs\b(main.js)とcss(style.css)を入れる。お節介ならfalseにする。\n",[235,4944,4945,4947,4949,4951,4953,4955],{"class":237,"line":604},[235,4946,4670],{"class":495},[235,4948,500],{"class":499},[235,4950,1345],{"class":499},[235,4952,4677],{"class":245},[235,4954,1345],{"class":499},[235,4956,1984],{"class":499},[235,4958,4959],{"class":237,"line":612},[235,4960,263],{"emptyLinePlaceholder":262},[235,4962,4963],{"class":237,"line":623},[235,4964,4965],{"class":3119},"        \u002F\u002F 対象のhtmlファイル\n",[235,4967,4968,4970,4972,4974],{"class":237,"line":634},[235,4969,4686],{"class":495},[235,4971,500],{"class":499},[235,4973,4548],{"class":519},[235,4975,1984],{"class":499},[235,4977,4978],{"class":237,"line":641},[235,4979,263],{"emptyLinePlaceholder":262},[235,4981,4982],{"class":237,"line":653},[235,4983,4984],{"class":3119},"        \u002F\u002F 圧縮するかどうか。defaultはtrue\n",[235,4986,4987,4989,4991],{"class":237,"line":661},[235,4988,4697],{"class":495},[235,4990,500],{"class":499},[235,4992,4703],{"class":4702},[235,4994,4995,4997],{"class":237,"line":670},[235,4996,4708],{"class":499},[235,4998,1953],{"class":495},[235,5000,5001],{"class":237,"line":678},[235,5002,4715],{"class":495},[235,5004,5005,5007,5009],{"class":237,"line":686},[235,5006,1950],{"class":499},[235,5008,1715],{"class":519},[235,5010,1348],{"class":499},[13,5012,5013,5016,5017,5019],{},[39,5014,5015],{},"new HtmlWebpackPlugin()","では対象のHTMLファイルをwebpackに読み込ませますが、１ファイルづつなのでhtmlが複数ある場合、",[39,5018,4320],{},"などを使用して複数の対象ファイルを取得してforeachで回します。",[13,5021,5022,5023,5025,5026,1209,5028,5030],{},"こうすることで",[39,5024,4743],{},"配下のhtmlがバンドルされます。適当に内容を書いてnpm run buildしてみましょう。dist配下に",[39,5027,3951],{},[39,5029,3954],{},"が出力されるはずです。",[1225,5032,5034,5037],{"className":5033},[1228,2914],[39,5035,5036],{},"inject:'body'","がある場合、htmlにはバンドル対象のcss\u002Fjsを読み込む為のscriptやlinkを記述する必要はありません。自動的に挿入されます。\n",[81,5039,5040],{"id":5040},"画像パスの解決",[13,5042,5043,5044,1216,5046,5048],{},"HTML編の最後に画像パスの解決を行います。",[39,5045,3967],{},[39,5047,3925],{},"などロード可能な属性を見つけるとそのパスなどの解決を行おうとします。たとえば以下のようなタグある場合",[226,5050,5053],{"className":5051,"code":5052,"language":3947,"meta":231,"style":231},"language-html shiki shiki-themes material-theme-ocean","\u003C!-- バンドル前 -->\n\u003Cimg src=\"image.png\"\u002F>\n\n\u003C!-- バンドル後 -->\n\u003Cimg src=\".\u002Fimage.png\"\u002F>\n",[39,5054,5055,5060,5082,5086,5091],{"__ignoreMap":231},[235,5056,5057],{"class":237,"line":238},[235,5058,5059],{"class":3119},"\u003C!-- バンドル前 -->\n",[235,5061,5062,5064,5067,5070,5072,5074,5077,5079],{"class":237,"line":249},[235,5063,1481],{"class":499},[235,5065,5066],{"class":495},"img",[235,5068,5069],{"class":1375}," src",[235,5071,1382],{"class":499},[235,5073,1517],{"class":499},[235,5075,5076],{"class":245},"image.png",[235,5078,1517],{"class":499},[235,5080,5081],{"class":499},"\u002F>\n",[235,5083,5084],{"class":237,"line":259},[235,5085,263],{"emptyLinePlaceholder":262},[235,5087,5088],{"class":237,"line":266},[235,5089,5090],{"class":3119},"\u003C!-- バンドル後 -->\n",[235,5092,5093,5095,5097,5099,5101,5103,5106,5108],{"class":237,"line":275},[235,5094,1481],{"class":499},[235,5096,5066],{"class":495},[235,5098,5069],{"class":1375},[235,5100,1382],{"class":499},[235,5102,1517],{"class":499},[235,5104,5105],{"class":245},".\u002Fimage.png",[235,5107,1517],{"class":499},[235,5109,5081],{"class":499},[13,5111,5112,5113,5115],{},"このように自動的にパスの調整を行います。相対パスだと階層が深い時大変ですので、scssではエイリアスを用いて",[39,5114,3925],{},"を指定できましたが、htmlは残念ながらできません。",[226,5117,5119],{"className":5051,"code":5118,"language":3947,"meta":231,"style":231},"\u003C!-- バンドル前 -->\n\u003Cimg src=\"~\u002Fimg\u002Fimage.png\"\u002F>\n\n\u003C!-- Module not found -->\n",[39,5120,5121,5125,5144,5148],{"__ignoreMap":231},[235,5122,5123],{"class":237,"line":238},[235,5124,5059],{"class":3119},[235,5126,5127,5129,5131,5133,5135,5137,5140,5142],{"class":237,"line":249},[235,5128,1481],{"class":499},[235,5130,5066],{"class":495},[235,5132,5069],{"class":1375},[235,5134,1382],{"class":499},[235,5136,1517],{"class":499},[235,5138,5139],{"class":245},"~\u002Fimg\u002Fimage.png",[235,5141,1517],{"class":499},[235,5143,5081],{"class":499},[235,5145,5146],{"class":237,"line":259},[235,5147,263],{"emptyLinePlaceholder":262},[235,5149,5150],{"class":237,"line":266},[235,5151,5152],{"class":3119},"\u003C!-- Module not found -->\n",[13,5154,5155,5156,3710,5158,5160],{},"しかし対処法はあります。",[39,5157,2046],{},[39,5159,2158],{},"にrootsプロパティーを記述します。",[226,5162,5164],{"className":3990,"code":5163,"filename":2046,"language":3992,"meta":231,"style":231},"const buildDefault = {\n    resolve:{\n        extensions: ['.js', '.json', '.scss', '.css'],\n        alias: {\n            '~': path.resolve(__dirname, 'src'),\n        },\n        \u002F\u002F ↓追加！\n        roots: [path.resolve(__dirname, \"src\")],\n    },\n}\n",[39,5165,5166,5176,5183,5231,5240,5272,5277,5282,5311,5315],{"__ignoreMap":231},[235,5167,5168,5170,5172,5174],{"class":237,"line":238},[235,5169,1376],{"class":1375},[235,5171,4111],{"class":519},[235,5173,1382],{"class":499},[235,5175,1276],{"class":499},[235,5177,5178,5180],{"class":237,"line":249},[235,5179,2127],{"class":495},[235,5181,5182],{"class":499},":{\n",[235,5184,5185,5188,5190,5193,5195,5198,5200,5202,5204,5207,5209,5211,5213,5216,5218,5220,5222,5225,5227,5229],{"class":237,"line":259},[235,5186,5187],{"class":495},"        extensions",[235,5189,500],{"class":499},[235,5191,5192],{"class":519}," [",[235,5194,1345],{"class":499},[235,5196,5197],{"class":245},".js",[235,5199,1345],{"class":499},[235,5201,1404],{"class":499},[235,5203,503],{"class":499},[235,5205,5206],{"class":245},".json",[235,5208,1345],{"class":499},[235,5210,1404],{"class":499},[235,5212,503],{"class":499},[235,5214,5215],{"class":245},".scss",[235,5217,1345],{"class":499},[235,5219,1404],{"class":499},[235,5221,503],{"class":499},[235,5223,5224],{"class":245},".css",[235,5226,1345],{"class":499},[235,5228,4585],{"class":519},[235,5230,1984],{"class":499},[235,5232,5233,5236,5238],{"class":237,"line":266},[235,5234,5235],{"class":495},"        alias",[235,5237,500],{"class":499},[235,5239,1276],{"class":499},[235,5241,5242,5245,5248,5250,5252,5254,5256,5258,5260,5262,5264,5266,5268,5270],{"class":237,"line":275},[235,5243,5244],{"class":499},"            '",[235,5246,5247],{"class":495},"~",[235,5249,1345],{"class":499},[235,5251,500],{"class":499},[235,5253,1393],{"class":519},[235,5255,1694],{"class":499},[235,5257,2158],{"class":252},[235,5259,4640],{"class":519},[235,5261,1404],{"class":499},[235,5263,503],{"class":499},[235,5265,3925],{"class":245},[235,5267,1345],{"class":499},[235,5269,1715],{"class":519},[235,5271,1984],{"class":499},[235,5273,5274],{"class":237,"line":283},[235,5275,5276],{"class":499},"        },\n",[235,5278,5279],{"class":237,"line":291},[235,5280,5281],{"class":3119},"        \u002F\u002F ↓追加！\n",[235,5283,5284,5287,5289,5292,5294,5296,5298,5300,5302,5304,5306,5309],{"class":237,"line":298},[235,5285,5286],{"class":495},"        roots",[235,5288,500],{"class":499},[235,5290,5291],{"class":519}," [path",[235,5293,1694],{"class":499},[235,5295,2158],{"class":252},[235,5297,4640],{"class":519},[235,5299,1404],{"class":499},[235,5301,595],{"class":499},[235,5303,3925],{"class":245},[235,5305,1517],{"class":499},[235,5307,5308],{"class":519},")]",[235,5310,1984],{"class":499},[235,5312,5313],{"class":237,"line":380},[235,5314,4091],{"class":499},[235,5316,5317],{"class":237,"line":465},[235,5318,1317],{"class":499},[13,5320,5321],{},"このrootsプロパティを追加した後、パスは以下のようにします。",[226,5323,5325],{"className":5051,"code":5324,"language":3947,"meta":231,"style":231},"\u003C!-- バンドル前 -->\n\u003Cimg src=\"\u002Fimg\u002Fimage.png\"\u002F>\n\n\u003C!-- バンドル後 -->\n\u003Cimg src=\"img\u002Fimage.png\"\u002F>\n",[39,5326,5327,5331,5350,5354,5358],{"__ignoreMap":231},[235,5328,5329],{"class":237,"line":238},[235,5330,5059],{"class":3119},[235,5332,5333,5335,5337,5339,5341,5343,5346,5348],{"class":237,"line":249},[235,5334,1481],{"class":499},[235,5336,5066],{"class":495},[235,5338,5069],{"class":1375},[235,5340,1382],{"class":499},[235,5342,1517],{"class":499},[235,5344,5345],{"class":245},"\u002Fimg\u002Fimage.png",[235,5347,1517],{"class":499},[235,5349,5081],{"class":499},[235,5351,5352],{"class":237,"line":259},[235,5353,263],{"emptyLinePlaceholder":262},[235,5355,5356],{"class":237,"line":266},[235,5357,5090],{"class":3119},[235,5359,5360,5362,5364,5366,5368,5370,5373,5375],{"class":237,"line":275},[235,5361,1481],{"class":499},[235,5363,5066],{"class":495},[235,5365,5069],{"class":1375},[235,5367,1382],{"class":499},[235,5369,1517],{"class":499},[235,5371,5372],{"class":245},"img\u002Fimage.png",[235,5374,1517],{"class":499},[235,5376,5081],{"class":499},[13,5378,5379,5382,5383,5385,5386,5389],{},[39,5380,5381],{},"roots: [path.resolve(__dirname, \"src\")],","によって",[39,5384,5345],{},"のパスを",[39,5387,5388],{},"src\u002F","を基準に探してくれるようになります。HTMLの場合はこのようにして画像を指定します。",[74,5391,5393],{"id":5392},"pugでhtmlファイルをバンドルする","pugでHTMLファイルをバンドルする",[13,5395,5396,5397,5399],{},"ひとまず以上の設定でhtmlファイルが使用できるようになりました。",[39,5398,4743],{},"配下で必要なページ分だけのHTMLを作成して、スタイルはscss、jsも一つにまとめられてスマートに見えます。しかし、繰り返しの記述をしたりテンプレートを作成してより効率的に描きたい時もあると思います。そんな時、テンプレートエンジンと呼ばれるものを使用することでより効率よくマークアップができるようになります。今回はpugを用います。（他の候補としてEJSなどがある）",[81,5401,5402],{"id":5402},"pugの使い方",[13,5404,5405],{},"今回は詳しい説明は省略しますが、概要的に伝えます。pugは以下のような記述でhtmlのマークアップが可能です。",[13,5407,5408],{},"レイアウトテンプレートファイル",[226,5410,5415],{"className":5411,"code":5412,"filename":5413,"language":5414,"meta":231,"style":231},"language-pug shiki shiki-themes material-theme-ocean","doctype html\nhtml(lang=\"ja\")\n    block head\n        include ..\u002Fcomponents\u002Fhead_conf\n    body\n        .body-wrapper\n            block header\n                include ..\u002Fcomponents\u002Fheader\n\n            main.p-main-content\n                block content\n\n            block footer\n                include ..\u002Fcomponents\u002Ffooter\n            \n            block footerNav \n                include ..\u002Fcomponents\u002FfooterNav\n","layout\u002Fdefault.pug","pug",[39,5416,5417,5422,5427,5432,5437,5442,5447,5452,5457,5461,5466,5471,5475,5480,5485,5490,5495],{"__ignoreMap":231},[235,5418,5419],{"class":237,"line":238},[235,5420,5421],{},"doctype html\n",[235,5423,5424],{"class":237,"line":249},[235,5425,5426],{},"html(lang=\"ja\")\n",[235,5428,5429],{"class":237,"line":259},[235,5430,5431],{},"    block head\n",[235,5433,5434],{"class":237,"line":266},[235,5435,5436],{},"        include ..\u002Fcomponents\u002Fhead_conf\n",[235,5438,5439],{"class":237,"line":275},[235,5440,5441],{},"    body\n",[235,5443,5444],{"class":237,"line":283},[235,5445,5446],{},"        .body-wrapper\n",[235,5448,5449],{"class":237,"line":291},[235,5450,5451],{},"            block header\n",[235,5453,5454],{"class":237,"line":298},[235,5455,5456],{},"                include ..\u002Fcomponents\u002Fheader\n",[235,5458,5459],{"class":237,"line":380},[235,5460,263],{"emptyLinePlaceholder":262},[235,5462,5463],{"class":237,"line":465},[235,5464,5465],{},"            main.p-main-content\n",[235,5467,5468],{"class":237,"line":590},[235,5469,5470],{},"                block content\n",[235,5472,5473],{"class":237,"line":604},[235,5474,263],{"emptyLinePlaceholder":262},[235,5476,5477],{"class":237,"line":612},[235,5478,5479],{},"            block footer\n",[235,5481,5482],{"class":237,"line":623},[235,5483,5484],{},"                include ..\u002Fcomponents\u002Ffooter\n",[235,5486,5487],{"class":237,"line":634},[235,5488,5489],{},"            \n",[235,5491,5492],{"class":237,"line":641},[235,5493,5494],{},"            block footerNav \n",[235,5496,5497],{"class":237,"line":653},[235,5498,5499],{},"                include ..\u002Fcomponents\u002FfooterNav\n",[13,5501,5502,5503,5506],{},"main配下のページ内容（上記のテンプレートファイルの",[39,5504,5505],{},"block content","に展開）",[226,5508,5511],{"className":5411,"code":5509,"filename":5510,"language":5414,"meta":231,"style":231},"extends ..\u002Flayouts\u002Fdefault.pug\ninclude ..\u002Fcomponents\u002Fbadge\n    include ..\u002Fcomponents\u002F_data\n        - var recommneds = variables.recommneds\n\nblock content\n    .p-first-view-content\n        .p-sliders.swiper(id=\"top-slider\")\n            .p-slider-wrapper.swiper-wrapper\n                .c-slider.swiper-slide\n                    .c-img-adjuster\n                        img(src=require(\"~\u002Fimg\u002Fsample\u002Ftop_slider_img.jpg\"), alt=\"スライダーの写真\")\n                .c-slider.swiper-slide\n                    .c-img-adjuster\n                        img(src=require(\"~\u002Fimg\u002Fsample\u002Ftop_slider_img.jpg\"), alt=\"スライダーの写真\")\n    \n    div.p-fullfilled\n        .p-row-container\n            .p-row-wrapper\n                each val,index in recommneds\n                    +badge(val,\"recommend-\"+index)\n","pages\u002Findex.pug",[39,5512,5513,5518,5523,5528,5533,5537,5542,5547,5552,5557,5562,5567,5572,5576,5580,5584,5588,5593,5598,5603,5608],{"__ignoreMap":231},[235,5514,5515],{"class":237,"line":238},[235,5516,5517],{},"extends ..\u002Flayouts\u002Fdefault.pug\n",[235,5519,5520],{"class":237,"line":249},[235,5521,5522],{},"include ..\u002Fcomponents\u002Fbadge\n",[235,5524,5525],{"class":237,"line":259},[235,5526,5527],{},"    include ..\u002Fcomponents\u002F_data\n",[235,5529,5530],{"class":237,"line":266},[235,5531,5532],{},"        - var recommneds = variables.recommneds\n",[235,5534,5535],{"class":237,"line":275},[235,5536,263],{"emptyLinePlaceholder":262},[235,5538,5539],{"class":237,"line":283},[235,5540,5541],{},"block content\n",[235,5543,5544],{"class":237,"line":291},[235,5545,5546],{},"    .p-first-view-content\n",[235,5548,5549],{"class":237,"line":298},[235,5550,5551],{},"        .p-sliders.swiper(id=\"top-slider\")\n",[235,5553,5554],{"class":237,"line":380},[235,5555,5556],{},"            .p-slider-wrapper.swiper-wrapper\n",[235,5558,5559],{"class":237,"line":465},[235,5560,5561],{},"                .c-slider.swiper-slide\n",[235,5563,5564],{"class":237,"line":590},[235,5565,5566],{},"                    .c-img-adjuster\n",[235,5568,5569],{"class":237,"line":604},[235,5570,5571],{},"                        img(src=require(\"~\u002Fimg\u002Fsample\u002Ftop_slider_img.jpg\"), alt=\"スライダーの写真\")\n",[235,5573,5574],{"class":237,"line":612},[235,5575,5561],{},[235,5577,5578],{"class":237,"line":623},[235,5579,5566],{},[235,5581,5582],{"class":237,"line":634},[235,5583,5571],{},[235,5585,5586],{"class":237,"line":641},[235,5587,4160],{},[235,5589,5590],{"class":237,"line":653},[235,5591,5592],{},"    div.p-fullfilled\n",[235,5594,5595],{"class":237,"line":661},[235,5596,5597],{},"        .p-row-container\n",[235,5599,5600],{"class":237,"line":670},[235,5601,5602],{},"            .p-row-wrapper\n",[235,5604,5605],{"class":237,"line":678},[235,5606,5607],{},"                each val,index in recommneds\n",[235,5609,5610],{"class":237,"line":686},[235,5611,5612],{},"                    +badge(val,\"recommend-\"+index)\n",[13,5614,5615],{},"for文によるループ、テンプレート、mixinやインポートなどPHPなどバック側で行っていたような、htmlの構築ができます。laravelのbladeみたいな感じです。pugを使うことでhtmlで面倒と思っていたことは大体解消できます。変更にも強いのでpugは使うことをお勧めします。",[81,5617,5618],{"id":5618},"ディレクトリを少し変更",[13,5620,5621,5622,5624],{},"htmlの時は単に",[39,5623,4743],{},"配下にファイルを配置するだけでしたが、もう少しpugで管理しやすいように以下のように変更します。",[226,5626,5629],{"className":5627,"code":5628,"language":934},[932],".\n├── dist\n├── package-lock.json\n├── package.json\n├── src\n│   ├── imgs\n│   ├── html\n│   │   ├── component\n│   │   ├── layout\n│   │   └── page\n│   ├── js\n│   │   ├── functions.js\n│   │   └── main.js\n│   └── sass\n│       ├── compnent.scss\n│       ├── style.scss\n│       └── variable.scss\n├── node_modules\n└── webpack.config.js\n",[39,5630,5628],{"__ignoreMap":231},[13,5632,5633,1404,5636,1404,5639,5642,5643,5645,5646,5648,5649,5651],{},[39,5634,5635],{},"component",[39,5637,5638],{},"layout",[39,5640,5641],{},"page",",というものを追加しました。",[39,5644,5635],{},"は繰り返し使われるパーツ（ボタンとかカードとか）のpugを格納、",[39,5647,5638],{},"はhead,bodyの構成を含めたmainタグ以外の箇所のレイアウトを決めるpugを格納し、",[39,5650,5641],{},"にバンドル対象の各種ページのpugを配置します。",[13,5653,5654,5656,5657,1209,5660,5663,5664,5666],{},[39,5655,5641],{},"に先ほどの",[39,5658,5659],{},"index.pug",[39,5661,5662],{}," detail.pug","を配置して、最終的にhtmlにして",[39,5665,3921],{},"に配置します。適宜component、layoutからファイルをインポートして使用します。私は大体のプロジェクトはこれで十分なカバーできる気がします。",[81,5668,5669],{"id":5669},"webpackでpugを扱う",[13,5671,5672],{},"それではwebpackでpugを扱えるようにしましょう。以下のloaderとpluginを入れます。",[226,5674,5677],{"className":5675,"code":5676,"language":934},[932],"npm install -D pug-loader html-webpack-plugin\n",[39,5678,5676],{"__ignoreMap":231},[13,5680,5681,5683],{},[39,5682,4236],{}," はHTML編でここでは入っていれば入りません。",[13,5685,5686,5687,5689],{},"まずは",[39,5688,3986],{},"にpugのruleとloaderを追加します。",[226,5691,5693],{"className":3990,"code":5692,"filename":2046,"language":3992,"meta":231,"style":231},"\n\u002F\u002F rulesの配列は後で\nlet rules = [\n    \u002F\u002F ... \n    \u002F\u002F 追加↓\n    {\n        test: \u002F\\.pug$\u002F,\n        exclude: \u002Fnode_modules\u002F,\n        use: [\n          {\n            loader: 'pug-loader',\n            options: {\n              pretty: true,\n            }\n          }\n        ]\n    }\n    \u002F\u002F ...\n]\n\nconst buildDefault = = {\n    entry: '.\u002Fsrc\u002Fjs\u002Fmain.js',\n  \n    mode:\"development\",\n    \n    module: {\n        rules: rules\n    },\n\n    rules:rules,\n    \u002F\u002F ...\n}\n\u002F\u002F...\n\nmodule.exports = buildDefault;\n",[39,5694,5695,5699,5703,5713,5717,5721,5725,5743,5759,5767,5772,5787,5796,5808,5813,5818,5823,5827,5831,5835,5839,5851,5865,5869,5883,5887,5895,5903,5907,5911,5921,5925,5929,5933,5937],{"__ignoreMap":231},[235,5696,5697],{"class":237,"line":238},[235,5698,263],{"emptyLinePlaceholder":262},[235,5700,5701],{"class":237,"line":249},[235,5702,4003],{"class":3119},[235,5704,5705,5707,5709,5711],{"class":237,"line":259},[235,5706,4008],{"class":1375},[235,5708,4011],{"class":519},[235,5710,1382],{"class":499},[235,5712,1385],{"class":519},[235,5714,5715],{"class":237,"line":266},[235,5716,4020],{"class":3119},[235,5718,5719],{"class":237,"line":275},[235,5720,4025],{"class":3119},[235,5722,5723],{"class":237,"line":283},[235,5724,4030],{"class":499},[235,5726,5727,5729,5731,5733,5735,5737,5739,5741],{"class":237,"line":291},[235,5728,4035],{"class":495},[235,5730,500],{"class":499},[235,5732,4040],{"class":499},[235,5734,4043],{"class":519},[235,5736,5414],{"class":245},[235,5738,4052],{"class":1269},[235,5740,4055],{"class":499},[235,5742,1984],{"class":499},[235,5744,5745,5748,5750,5752,5755,5757],{"class":237,"line":298},[235,5746,5747],{"class":495},"        exclude",[235,5749,500],{"class":499},[235,5751,4040],{"class":499},[235,5753,5754],{"class":245},"node_modules",[235,5756,4055],{"class":499},[235,5758,1984],{"class":499},[235,5760,5761,5763,5765],{"class":237,"line":380},[235,5762,4062],{"class":495},[235,5764,500],{"class":499},[235,5766,1385],{"class":519},[235,5768,5769],{"class":237,"line":465},[235,5770,5771],{"class":499},"          {\n",[235,5773,5774,5776,5778,5780,5783,5785],{"class":237,"line":590},[235,5775,4071],{"class":495},[235,5777,500],{"class":499},[235,5779,503],{"class":499},[235,5781,5782],{"class":245},"pug-loader",[235,5784,1345],{"class":499},[235,5786,1984],{"class":499},[235,5788,5789,5792,5794],{"class":237,"line":604},[235,5790,5791],{"class":495},"            options",[235,5793,500],{"class":499},[235,5795,1276],{"class":499},[235,5797,5798,5801,5803,5806],{"class":237,"line":612},[235,5799,5800],{"class":495},"              pretty",[235,5802,500],{"class":499},[235,5804,5805],{"class":4702}," true",[235,5807,1984],{"class":499},[235,5809,5810],{"class":237,"line":623},[235,5811,5812],{"class":499},"            }\n",[235,5814,5815],{"class":237,"line":634},[235,5816,5817],{"class":499},"          }\n",[235,5819,5820],{"class":237,"line":641},[235,5821,5822],{"class":519},"        ]\n",[235,5824,5825],{"class":237,"line":653},[235,5826,2181],{"class":499},[235,5828,5829],{"class":237,"line":661},[235,5830,4096],{"class":3119},[235,5832,5833],{"class":237,"line":670},[235,5834,1444],{"class":519},[235,5836,5837],{"class":237,"line":678},[235,5838,263],{"emptyLinePlaceholder":262},[235,5840,5841,5843,5845,5847,5849],{"class":237,"line":686},[235,5842,1376],{"class":1375},[235,5844,4111],{"class":519},[235,5846,1382],{"class":499},[235,5848,4116],{"class":499},[235,5850,1276],{"class":499},[235,5852,5853,5855,5857,5859,5861,5863],{"class":237,"line":694},[235,5854,4123],{"class":495},[235,5856,500],{"class":499},[235,5858,503],{"class":499},[235,5860,4130],{"class":245},[235,5862,1345],{"class":499},[235,5864,1984],{"class":499},[235,5866,5867],{"class":237,"line":702},[235,5868,4139],{"class":519},[235,5870,5871,5873,5875,5877,5879,5881],{"class":237,"line":712},[235,5872,4144],{"class":495},[235,5874,500],{"class":499},[235,5876,1517],{"class":499},[235,5878,4151],{"class":245},[235,5880,1517],{"class":499},[235,5882,1984],{"class":499},[235,5884,5885],{"class":237,"line":723},[235,5886,4160],{"class":519},[235,5888,5889,5891,5893],{"class":237,"line":730},[235,5890,4165],{"class":495},[235,5892,500],{"class":499},[235,5894,1276],{"class":499},[235,5896,5897,5899,5901],{"class":237,"line":741},[235,5898,4174],{"class":495},[235,5900,500],{"class":499},[235,5902,4179],{"class":519},[235,5904,5905],{"class":237,"line":752},[235,5906,4091],{"class":499},[235,5908,5909],{"class":237,"line":763},[235,5910,263],{"emptyLinePlaceholder":262},[235,5912,5913,5915,5917,5919],{"class":237,"line":774},[235,5914,4192],{"class":495},[235,5916,500],{"class":499},[235,5918,3986],{"class":519},[235,5920,1984],{"class":499},[235,5922,5923],{"class":237,"line":785},[235,5924,4096],{"class":3119},[235,5926,5927],{"class":237,"line":794},[235,5928,1317],{"class":499},[235,5930,5931],{"class":237,"line":806},[235,5932,4211],{"class":3119},[235,5934,5935],{"class":237,"line":815},[235,5936,263],{"emptyLinePlaceholder":262},[235,5938,5939,5941,5943,5945],{"class":237,"line":823},[235,5940,4220],{"class":499},[235,5942,4116],{"class":499},[235,5944,4225],{"class":519},[235,5946,1348],{"class":499},[13,5948,5949],{},"次に",[226,5951,5953],{"className":3990,"code":5952,"filename":2046,"language":3992,"meta":231,"style":231},"\u002F\u002F ファイル冒頭\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst path = require('path');\n\n\u002F\u002F この２つを追加\nconst globule = require('globule');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\n\nlet rules = [\n    \u002F\u002F 省略... \n]\n\nconst buildDefault = = {\n    entry: '.\u002Fsrc\u002Fjs\u002Fmain.js',\n  \n    mode:\"development\",\n    \n    module: {\n        rules: rules\n    },\n\n    rules:rules,\n    \u002F\u002F 以下略...\n}\n\n\u002F\u002F これらを追記\nconst pugFiles = globule.find('src\u002Fhtml\u002Fpage\u002F*', {\n    ignore: [ 'src\u002Fhtml\u002Fcomponents\u002F*','src\u002Fhtml.layouts\u002F*' ]\n});\n\npugFiles.forEach((pug) => {\n    const html = pug.split('\u002F').slice(-1)[0].replace('.pug', '.html');\n    buildDefault.plugins.push(\n      new HtmlWebpackPlugin({\n        filename: `${path.resolve(__dirname, 'dist')}\u002F${html}`,\n        inject:'body',\n        template: pug,\n        minify: false\n      })\n    )\n});\n\nmodule.exports = buildDefault;\n",[39,5954,5955,5959,5981,6003,6007,6011,6033,6055,6059,6069,6073,6077,6081,6093,6107,6111,6125,6129,6137,6145,6149,6153,6163,6167,6171,6175,6179,6207,6236,6244,6248,6269,6338,6352,6362,6400,6414,6424,6432,6438,6442,6450,6454],{"__ignoreMap":231},[235,5956,5957],{"class":237,"line":238},[235,5958,4247],{"class":3119},[235,5960,5961,5963,5965,5967,5969,5971,5973,5975,5977,5979],{"class":237,"line":249},[235,5962,1376],{"class":1375},[235,5964,4254],{"class":519},[235,5966,1382],{"class":499},[235,5968,1702],{"class":252},[235,5970,1705],{"class":519},[235,5972,1345],{"class":499},[235,5974,4265],{"class":245},[235,5976,1345],{"class":499},[235,5978,1715],{"class":519},[235,5980,1348],{"class":499},[235,5982,5983,5985,5987,5989,5991,5993,5995,5997,5999,6001],{"class":237,"line":259},[235,5984,1376],{"class":1375},[235,5986,2087],{"class":519},[235,5988,1382],{"class":499},[235,5990,1702],{"class":252},[235,5992,1705],{"class":519},[235,5994,1345],{"class":499},[235,5996,2098],{"class":245},[235,5998,1345],{"class":499},[235,6000,1715],{"class":519},[235,6002,1348],{"class":499},[235,6004,6005],{"class":237,"line":266},[235,6006,263],{"emptyLinePlaceholder":262},[235,6008,6009],{"class":237,"line":275},[235,6010,4302],{"class":3119},[235,6012,6013,6015,6017,6019,6021,6023,6025,6027,6029,6031],{"class":237,"line":283},[235,6014,1376],{"class":1375},[235,6016,4309],{"class":519},[235,6018,1382],{"class":499},[235,6020,1702],{"class":252},[235,6022,1705],{"class":519},[235,6024,1345],{"class":499},[235,6026,4320],{"class":245},[235,6028,1345],{"class":499},[235,6030,1715],{"class":519},[235,6032,1348],{"class":499},[235,6034,6035,6037,6039,6041,6043,6045,6047,6049,6051,6053],{"class":237,"line":291},[235,6036,1376],{"class":1375},[235,6038,4333],{"class":519},[235,6040,1382],{"class":499},[235,6042,1702],{"class":252},[235,6044,1705],{"class":519},[235,6046,1345],{"class":499},[235,6048,4236],{"class":245},[235,6050,1345],{"class":499},[235,6052,1715],{"class":519},[235,6054,1348],{"class":499},[235,6056,6057],{"class":237,"line":298},[235,6058,263],{"emptyLinePlaceholder":262},[235,6060,6061,6063,6065,6067],{"class":237,"line":380},[235,6062,4008],{"class":1375},[235,6064,4011],{"class":519},[235,6066,1382],{"class":499},[235,6068,1385],{"class":519},[235,6070,6071],{"class":237,"line":465},[235,6072,4368],{"class":3119},[235,6074,6075],{"class":237,"line":590},[235,6076,1444],{"class":519},[235,6078,6079],{"class":237,"line":604},[235,6080,263],{"emptyLinePlaceholder":262},[235,6082,6083,6085,6087,6089,6091],{"class":237,"line":612},[235,6084,1376],{"class":1375},[235,6086,4111],{"class":519},[235,6088,1382],{"class":499},[235,6090,4116],{"class":499},[235,6092,1276],{"class":499},[235,6094,6095,6097,6099,6101,6103,6105],{"class":237,"line":623},[235,6096,4123],{"class":495},[235,6098,500],{"class":499},[235,6100,503],{"class":499},[235,6102,4130],{"class":245},[235,6104,1345],{"class":499},[235,6106,1984],{"class":499},[235,6108,6109],{"class":237,"line":634},[235,6110,4139],{"class":519},[235,6112,6113,6115,6117,6119,6121,6123],{"class":237,"line":641},[235,6114,4144],{"class":495},[235,6116,500],{"class":499},[235,6118,1517],{"class":499},[235,6120,4151],{"class":245},[235,6122,1517],{"class":499},[235,6124,1984],{"class":499},[235,6126,6127],{"class":237,"line":653},[235,6128,4160],{"class":519},[235,6130,6131,6133,6135],{"class":237,"line":661},[235,6132,4165],{"class":495},[235,6134,500],{"class":499},[235,6136,1276],{"class":499},[235,6138,6139,6141,6143],{"class":237,"line":670},[235,6140,4174],{"class":495},[235,6142,500],{"class":499},[235,6144,4179],{"class":519},[235,6146,6147],{"class":237,"line":678},[235,6148,4091],{"class":499},[235,6150,6151],{"class":237,"line":686},[235,6152,263],{"emptyLinePlaceholder":262},[235,6154,6155,6157,6159,6161],{"class":237,"line":694},[235,6156,4192],{"class":495},[235,6158,500],{"class":499},[235,6160,3986],{"class":519},[235,6162,1984],{"class":499},[235,6164,6165],{"class":237,"line":702},[235,6166,4463],{"class":3119},[235,6168,6169],{"class":237,"line":712},[235,6170,1317],{"class":499},[235,6172,6173],{"class":237,"line":723},[235,6174,263],{"emptyLinePlaceholder":262},[235,6176,6177],{"class":237,"line":730},[235,6178,4476],{"class":3119},[235,6180,6181,6183,6186,6188,6190,6192,6194,6196,6198,6201,6203,6205],{"class":237,"line":741},[235,6182,1376],{"class":1375},[235,6184,6185],{"class":519}," pugFiles ",[235,6187,1382],{"class":499},[235,6189,4488],{"class":519},[235,6191,1694],{"class":499},[235,6193,4493],{"class":252},[235,6195,1705],{"class":519},[235,6197,1345],{"class":499},[235,6199,6200],{"class":245},"src\u002Fhtml\u002Fpage\u002F*",[235,6202,1345],{"class":499},[235,6204,1404],{"class":499},[235,6206,1276],{"class":499},[235,6208,6209,6212,6214,6217,6219,6222,6224,6226,6228,6231,6233],{"class":237,"line":752},[235,6210,6211],{"class":495},"    ignore",[235,6213,500],{"class":499},[235,6215,6216],{"class":519}," [ ",[235,6218,1345],{"class":499},[235,6220,6221],{"class":245},"src\u002Fhtml\u002Fcomponents\u002F*",[235,6223,1345],{"class":499},[235,6225,1404],{"class":499},[235,6227,1345],{"class":499},[235,6229,6230],{"class":245},"src\u002Fhtml.layouts\u002F*",[235,6232,1345],{"class":499},[235,6234,6235],{"class":519}," ]\n",[235,6237,6238,6240,6242],{"class":237,"line":763},[235,6239,1950],{"class":499},[235,6241,1715],{"class":519},[235,6243,1348],{"class":499},[235,6245,6246],{"class":237,"line":774},[235,6247,263],{"emptyLinePlaceholder":262},[235,6249,6250,6253,6255,6257,6259,6261,6263,6265,6267],{"class":237,"line":785},[235,6251,6252],{"class":519},"pugFiles",[235,6254,1694],{"class":499},[235,6256,4520],{"class":252},[235,6258,1705],{"class":519},[235,6260,1705],{"class":499},[235,6262,5414],{"class":4527},[235,6264,1715],{"class":499},[235,6266,4533],{"class":1375},[235,6268,1276],{"class":499},[235,6270,6271,6273,6276,6278,6281,6283,6285,6287,6289,6291,6293,6295,6297,6299,6301,6303,6305,6307,6309,6311,6313,6316,6318,6320,6323,6325,6327,6329,6332,6334,6336],{"class":237,"line":794},[235,6272,4540],{"class":1375},[235,6274,6275],{"class":519}," html",[235,6277,4116],{"class":499},[235,6279,6280],{"class":519}," pug",[235,6282,1694],{"class":499},[235,6284,4553],{"class":252},[235,6286,1705],{"class":495},[235,6288,1345],{"class":499},[235,6290,4055],{"class":245},[235,6292,1345],{"class":499},[235,6294,1715],{"class":495},[235,6296,1694],{"class":499},[235,6298,4568],{"class":252},[235,6300,1705],{"class":495},[235,6302,4573],{"class":499},[235,6304,4576],{"class":2836},[235,6306,4579],{"class":495},[235,6308,4582],{"class":2836},[235,6310,4585],{"class":495},[235,6312,1694],{"class":499},[235,6314,6315],{"class":252},"replace",[235,6317,1705],{"class":495},[235,6319,1345],{"class":499},[235,6321,6322],{"class":245},".pug",[235,6324,1345],{"class":499},[235,6326,1404],{"class":499},[235,6328,503],{"class":499},[235,6330,6331],{"class":245},".html",[235,6333,1345],{"class":499},[235,6335,1715],{"class":495},[235,6337,1348],{"class":499},[235,6339,6340,6342,6344,6346,6348,6350],{"class":237,"line":806},[235,6341,4596],{"class":519},[235,6343,1694],{"class":499},[235,6345,4601],{"class":519},[235,6347,1694],{"class":499},[235,6349,4606],{"class":252},[235,6351,4609],{"class":495},[235,6353,6354,6356,6358,6360],{"class":237,"line":815},[235,6355,4614],{"class":499},[235,6357,4617],{"class":252},[235,6359,1705],{"class":495},[235,6361,1976],{"class":499},[235,6363,6364,6366,6368,6370,6372,6374,6376,6378,6380,6382,6384,6386,6388,6390,6392,6394,6396,6398],{"class":237,"line":823},[235,6365,4626],{"class":495},[235,6367,500],{"class":499},[235,6369,4631],{"class":499},[235,6371,2098],{"class":519},[235,6373,1694],{"class":499},[235,6375,2158],{"class":252},[235,6377,4640],{"class":519},[235,6379,1404],{"class":499},[235,6381,503],{"class":499},[235,6383,3921],{"class":245},[235,6385,1345],{"class":499},[235,6387,1715],{"class":519},[235,6389,1950],{"class":499},[235,6391,4055],{"class":245},[235,6393,4657],{"class":499},[235,6395,3947],{"class":519},[235,6397,4663],{"class":499},[235,6399,1984],{"class":499},[235,6401,6402,6404,6406,6408,6410,6412],{"class":237,"line":833},[235,6403,4670],{"class":495},[235,6405,500],{"class":499},[235,6407,1345],{"class":499},[235,6409,4677],{"class":245},[235,6411,1345],{"class":499},[235,6413,1984],{"class":499},[235,6415,6416,6418,6420,6422],{"class":237,"line":3537},[235,6417,4686],{"class":495},[235,6419,500],{"class":499},[235,6421,6280],{"class":519},[235,6423,1984],{"class":499},[235,6425,6426,6428,6430],{"class":237,"line":3542},[235,6427,4697],{"class":495},[235,6429,500],{"class":499},[235,6431,4703],{"class":4702},[235,6433,6434,6436],{"class":237,"line":3547},[235,6435,4708],{"class":499},[235,6437,1953],{"class":495},[235,6439,6440],{"class":237,"line":3553},[235,6441,4715],{"class":495},[235,6443,6444,6446,6448],{"class":237,"line":3558},[235,6445,1950],{"class":499},[235,6447,1715],{"class":519},[235,6449,1348],{"class":499},[235,6451,6452],{"class":237,"line":3564},[235,6453,263],{"emptyLinePlaceholder":262},[235,6455,6456,6458,6460,6462],{"class":237,"line":4},[235,6457,4220],{"class":499},[235,6459,4116],{"class":499},[235,6461,4225],{"class":519},[235,6463,1348],{"class":499},[13,6465,6466],{},"詳細はHTML編の記述を見てください。HTML編と似ていますが、",[226,6468,6470],{"className":3990,"code":6469,"language":3992,"meta":231,"style":231},"const pugFiles = globule.find('src\u002Fhtml\u002F*', {\n    ignore: [ 'src\u002Fhtml\u002Fcomponents\u002F*','src\u002Fhtml.layouts\u002F*' ]\n});\n",[39,6471,6472,6499,6523],{"__ignoreMap":231},[235,6473,6474,6476,6478,6480,6482,6484,6486,6488,6490,6493,6495,6497],{"class":237,"line":238},[235,6475,1376],{"class":1375},[235,6477,6185],{"class":519},[235,6479,1382],{"class":499},[235,6481,4488],{"class":519},[235,6483,1694],{"class":499},[235,6485,4493],{"class":252},[235,6487,1705],{"class":519},[235,6489,1345],{"class":499},[235,6491,6492],{"class":245},"src\u002Fhtml\u002F*",[235,6494,1345],{"class":499},[235,6496,1404],{"class":499},[235,6498,1276],{"class":499},[235,6500,6501,6503,6505,6507,6509,6511,6513,6515,6517,6519,6521],{"class":237,"line":249},[235,6502,6211],{"class":495},[235,6504,500],{"class":499},[235,6506,6216],{"class":519},[235,6508,1345],{"class":499},[235,6510,6221],{"class":245},[235,6512,1345],{"class":499},[235,6514,1404],{"class":499},[235,6516,1345],{"class":499},[235,6518,6230],{"class":245},[235,6520,1345],{"class":499},[235,6522,6235],{"class":519},[235,6524,6525,6527,6529],{"class":237,"line":259},[235,6526,1950],{"class":499},[235,6528,1715],{"class":519},[235,6530,1348],{"class":499},[13,6532,6533,6535,6536,6539,6540,6542],{},[39,6534,4320],{},"では",[39,6537,6538],{},"ignore","を指定して全てのpugファイルを拾わないようにします。（今回の構成ならfindするディレクトリを ",[39,6541,6200],{}," にしてもいいかもしれません）",[13,6544,6545],{},"基本的にはこれでpugは使えるようになります。",[81,6547,6548],{"id":6548},"pugでの画像パスの解決",[13,6550,6551,6552,6554,6555,6558],{},"HTMLでは",[39,6553,2158],{},"で",[39,6556,6557],{},"roots","を指定していました。pugではそれらの指定は特に必要なく、以下のように指定します。",[226,6560,6562],{"className":5411,"code":6561,"language":5414,"meta":231,"style":231},"\u002F\u002F- OK\nimg(src=require(\"~\u002Fimg\u002Fsample.png\"), alt=\"\")\n\n\u002F\u002F- NG\nimg(src=\"~\u002Fimg\u002Fsample.png\", alt=\"\")\n",[39,6563,6564,6569,6574,6578,6583],{"__ignoreMap":231},[235,6565,6566],{"class":237,"line":238},[235,6567,6568],{},"\u002F\u002F- OK\n",[235,6570,6571],{"class":237,"line":249},[235,6572,6573],{},"img(src=require(\"~\u002Fimg\u002Fsample.png\"), alt=\"\")\n",[235,6575,6576],{"class":237,"line":259},[235,6577,263],{"emptyLinePlaceholder":262},[235,6579,6580],{"class":237,"line":266},[235,6581,6582],{},"\u002F\u002F- NG\n",[235,6584,6585],{"class":237,"line":275},[235,6586,6587],{},"img(src=\"~\u002Fimg\u002Fsample.png\", alt=\"\")\n",[13,6589,6590],{},"pugではnode.jsやjsの記述が利用できる為、requireを用いてエイリアスと一緒にパスの解決ができます。",[74,6592,6594],{"id":6593},"以上","以上！",[13,6596,6597,6598,6600],{},"以上でwebpackを用いたjs,scss,画像,htmlのバンドルは以上となります。vueやtypecriptの導入を考えるとさらに深い理解は必要そうですが、ひとまずHTMLのマークアップ程度であれば今回の構成を用いれば十分な気がします。vue・typesciptもいずれやってみようと思います。また今回使用した",[39,6599,2046],{},"は以下の通りとなります。参考にどうぞ。",[226,6602,6604],{"className":3990,"code":6603,"filename":2046,"language":3992,"meta":231,"style":231},"const MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst path = require('path');\nconst globule = require('globule');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\n  \nlet rules = [\n    {\n        test: \u002F\\.(sa|sc|c)ss$\u002F,\n        exclude: \u002Fnode_modules\u002F,\n        use: [\n            MiniCssExtractPlugin.loader,\n            {\n                loader: 'css-loader',\n                options: { url: true }\n            },\n            'sass-loader',\n        ],\n    },\n    {\n        test: \u002F\\.(png|jpg|gif|svg)$\u002Fi,\n        generator: {\n            filename: 'img\u002F[name][ext][query]'\n        },\n        type: 'asset\u002Fresource'\n    },\n    {\n        test: \u002F\\.(html)$\u002F,\n        use: {\n            loader: 'html-loader',\n        }\n     },\n    {\n        test: \u002F\\.pug$\u002F,\n        exclude: \u002Fnode_modules\u002F,\n        use: [\n          {\n            loader: 'pug-loader',\n            options: {\n              pretty: true,\n            }\n          }\n        ]\n    }\n]\n\nif(process.env.es5){\n    rules.push(\n        {\n            test: \u002F\\.m?js$\u002F,\n            exclude: \u002F(node_modules|bower_components)\u002F,\n            use: {\n              loader: 'babel-loader',\n              options: {\n                presets: ['@babel\u002Fpreset-env']\n              }\n            },\n            generator: {\n              filename: '[name].js'\n            }\n        }\n    )\n}\n\nconst buildDefault = {\n    entry:['.\u002Fsrc\u002Findex.js'],\n  \n    mode:process.env.mode,\n    \n    module: {\n        rules: rules\n    },\n    resolve:{\n        extensions: ['.js', '.json', '.scss', '.css'],\n        alias: {\n          '~': path.resolve(__dirname, 'src'),\n        },\n        roots: [path.resolve(__dirname, \"src\")],\n    },\n    \u002F\u002F ファイルの出力設定\n    output: {\n        \u002F\u002F  出力ファイルのディレクトリ名\n        path: `${__dirname}\u002Fdist`,\n        filename: '[name].js',\n    },\n    plugins: [\n        new MiniCssExtractPlugin({\n            filename: '[name].css'\n        }),\n    ]\n};\n\nconst pugFiles = globule.find('src\u002Fhtml\u002F*', {\n    ignore: [ 'src\u002Fhtml\u002Fcomponents\u002F*','src\u002Fhtml.layouts\u002F*' ]\n});\n\npugFiles.forEach((pug) => {\n    const html = pug.split('\u002F').slice(-1)[0].replace('.pug', '.html');\n    buildDefault.plugins.push(\n      new HtmlWebpackPlugin({\n        filename: `${path.resolve(__dirname, 'dist')}\u002F${html}`,\n        inject:'body',\n        template: pug,\n        minify: false\n      })\n    )\n});\n\nmodule.exports = buildDefault;\n",[39,6605,6606,6628,6650,6672,6694,6698,6708,6712,6749,6763,6771,6783,6788,6804,6824,6829,6840,6847,6851,6855,6896,6905,6919,6923,6937,6941,6945,6967,6975,6989,6993,6998,7002,7020,7034,7042,7046,7060,7068,7078,7082,7086,7090,7094,7098,7102,7122,7132,7137,7162,7184,7193,7209,7218,7236,7242,7247,7257,7272,7277,7282,7287,7292,7297,7308,7329,7334,7354,7359,7368,7377,7382,7389,7432,7441,7473,7478,7505,7510,7516,7526,7532,7555,7570,7575,7585,7598,7612,7622,7628,7634,7639,7666,7691,7700,7705,7726,7791,7806,7817,7856,7871,7882,7891,7898,7903,7912,7917],{"__ignoreMap":231},[235,6607,6608,6610,6612,6614,6616,6618,6620,6622,6624,6626],{"class":237,"line":238},[235,6609,1376],{"class":1375},[235,6611,4254],{"class":519},[235,6613,1382],{"class":499},[235,6615,1702],{"class":252},[235,6617,1705],{"class":519},[235,6619,1345],{"class":499},[235,6621,4265],{"class":245},[235,6623,1345],{"class":499},[235,6625,1715],{"class":519},[235,6627,1348],{"class":499},[235,6629,6630,6632,6634,6636,6638,6640,6642,6644,6646,6648],{"class":237,"line":249},[235,6631,1376],{"class":1375},[235,6633,2087],{"class":519},[235,6635,1382],{"class":499},[235,6637,1702],{"class":252},[235,6639,1705],{"class":519},[235,6641,1345],{"class":499},[235,6643,2098],{"class":245},[235,6645,1345],{"class":499},[235,6647,1715],{"class":519},[235,6649,1348],{"class":499},[235,6651,6652,6654,6656,6658,6660,6662,6664,6666,6668,6670],{"class":237,"line":259},[235,6653,1376],{"class":1375},[235,6655,4309],{"class":519},[235,6657,1382],{"class":499},[235,6659,1702],{"class":252},[235,6661,1705],{"class":519},[235,6663,1345],{"class":499},[235,6665,4320],{"class":245},[235,6667,1345],{"class":499},[235,6669,1715],{"class":519},[235,6671,1348],{"class":499},[235,6673,6674,6676,6678,6680,6682,6684,6686,6688,6690,6692],{"class":237,"line":266},[235,6675,1376],{"class":1375},[235,6677,4333],{"class":519},[235,6679,1382],{"class":499},[235,6681,1702],{"class":252},[235,6683,1705],{"class":519},[235,6685,1345],{"class":499},[235,6687,4236],{"class":245},[235,6689,1345],{"class":499},[235,6691,1715],{"class":519},[235,6693,1348],{"class":499},[235,6695,6696],{"class":237,"line":275},[235,6697,4139],{"class":519},[235,6699,6700,6702,6704,6706],{"class":237,"line":283},[235,6701,4008],{"class":1375},[235,6703,4011],{"class":519},[235,6705,1382],{"class":499},[235,6707,1385],{"class":519},[235,6709,6710],{"class":237,"line":291},[235,6711,4030],{"class":499},[235,6713,6714,6716,6718,6720,6722,6724,6727,6730,6733,6735,6738,6740,6743,6745,6747],{"class":237,"line":298},[235,6715,4035],{"class":495},[235,6717,500],{"class":499},[235,6719,4040],{"class":499},[235,6721,4043],{"class":519},[235,6723,1705],{"class":499},[235,6725,6726],{"class":245},"sa",[235,6728,6729],{"class":499},"|",[235,6731,6732],{"class":245},"sc",[235,6734,6729],{"class":499},[235,6736,6737],{"class":245},"c",[235,6739,1715],{"class":499},[235,6741,6742],{"class":245},"ss",[235,6744,4052],{"class":1269},[235,6746,4055],{"class":499},[235,6748,1984],{"class":499},[235,6750,6751,6753,6755,6757,6759,6761],{"class":237,"line":380},[235,6752,5747],{"class":495},[235,6754,500],{"class":499},[235,6756,4040],{"class":499},[235,6758,5754],{"class":245},[235,6760,4055],{"class":499},[235,6762,1984],{"class":499},[235,6764,6765,6767,6769],{"class":237,"line":465},[235,6766,4062],{"class":495},[235,6768,500],{"class":499},[235,6770,1385],{"class":519},[235,6772,6773,6776,6778,6781],{"class":237,"line":590},[235,6774,6775],{"class":519},"            MiniCssExtractPlugin",[235,6777,1694],{"class":499},[235,6779,6780],{"class":519},"loader",[235,6782,1984],{"class":499},[235,6784,6785],{"class":237,"line":604},[235,6786,6787],{"class":499},"            {\n",[235,6789,6790,6793,6795,6797,6800,6802],{"class":237,"line":612},[235,6791,6792],{"class":495},"                loader",[235,6794,500],{"class":499},[235,6796,503],{"class":499},[235,6798,6799],{"class":245},"css-loader",[235,6801,1345],{"class":499},[235,6803,1984],{"class":499},[235,6805,6806,6809,6811,6814,6817,6819,6821],{"class":237,"line":623},[235,6807,6808],{"class":495},"                options",[235,6810,500],{"class":499},[235,6812,6813],{"class":499}," {",[235,6815,6816],{"class":495}," url",[235,6818,500],{"class":499},[235,6820,5805],{"class":4702},[235,6822,6823],{"class":499}," }\n",[235,6825,6826],{"class":237,"line":634},[235,6827,6828],{"class":499},"            },\n",[235,6830,6831,6833,6836,6838],{"class":237,"line":641},[235,6832,5244],{"class":499},[235,6834,6835],{"class":245},"sass-loader",[235,6837,1345],{"class":499},[235,6839,1984],{"class":499},[235,6841,6842,6845],{"class":237,"line":653},[235,6843,6844],{"class":519},"        ]",[235,6846,1984],{"class":499},[235,6848,6849],{"class":237,"line":661},[235,6850,4091],{"class":499},[235,6852,6853],{"class":237,"line":670},[235,6854,4030],{"class":499},[235,6856,6857,6859,6861,6863,6865,6867,6870,6872,6875,6877,6880,6882,6885,6887,6889,6891,6894],{"class":237,"line":678},[235,6858,4035],{"class":495},[235,6860,500],{"class":499},[235,6862,4040],{"class":499},[235,6864,4043],{"class":519},[235,6866,1705],{"class":499},[235,6868,6869],{"class":245},"png",[235,6871,6729],{"class":499},[235,6873,6874],{"class":245},"jpg",[235,6876,6729],{"class":499},[235,6878,6879],{"class":245},"gif",[235,6881,6729],{"class":499},[235,6883,6884],{"class":245},"svg",[235,6886,1715],{"class":499},[235,6888,4052],{"class":1269},[235,6890,4055],{"class":499},[235,6892,6893],{"class":2836},"i",[235,6895,1984],{"class":499},[235,6897,6898,6901,6903],{"class":237,"line":686},[235,6899,6900],{"class":495},"        generator",[235,6902,500],{"class":499},[235,6904,1276],{"class":499},[235,6906,6907,6910,6912,6914,6917],{"class":237,"line":694},[235,6908,6909],{"class":495},"            filename",[235,6911,500],{"class":499},[235,6913,503],{"class":499},[235,6915,6916],{"class":245},"img\u002F[name][ext][query]",[235,6918,509],{"class":499},[235,6920,6921],{"class":237,"line":702},[235,6922,5276],{"class":499},[235,6924,6925,6928,6930,6932,6935],{"class":237,"line":712},[235,6926,6927],{"class":495},"        type",[235,6929,500],{"class":499},[235,6931,503],{"class":499},[235,6933,6934],{"class":245},"asset\u002Fresource",[235,6936,509],{"class":499},[235,6938,6939],{"class":237,"line":723},[235,6940,4091],{"class":499},[235,6942,6943],{"class":237,"line":730},[235,6944,4030],{"class":499},[235,6946,6947,6949,6951,6953,6955,6957,6959,6961,6963,6965],{"class":237,"line":741},[235,6948,4035],{"class":495},[235,6950,500],{"class":499},[235,6952,4040],{"class":499},[235,6954,4043],{"class":519},[235,6956,1705],{"class":499},[235,6958,3947],{"class":245},[235,6960,1715],{"class":499},[235,6962,4052],{"class":1269},[235,6964,4055],{"class":499},[235,6966,1984],{"class":499},[235,6968,6969,6971,6973],{"class":237,"line":752},[235,6970,4062],{"class":495},[235,6972,500],{"class":499},[235,6974,1276],{"class":499},[235,6976,6977,6979,6981,6983,6985,6987],{"class":237,"line":763},[235,6978,4071],{"class":495},[235,6980,500],{"class":499},[235,6982,503],{"class":499},[235,6984,3967],{"class":245},[235,6986,1345],{"class":499},[235,6988,1984],{"class":499},[235,6990,6991],{"class":237,"line":774},[235,6992,4086],{"class":499},[235,6994,6995],{"class":237,"line":785},[235,6996,6997],{"class":499},"     },\n",[235,6999,7000],{"class":237,"line":794},[235,7001,4030],{"class":499},[235,7003,7004,7006,7008,7010,7012,7014,7016,7018],{"class":237,"line":806},[235,7005,4035],{"class":495},[235,7007,500],{"class":499},[235,7009,4040],{"class":499},[235,7011,4043],{"class":519},[235,7013,5414],{"class":245},[235,7015,4052],{"class":1269},[235,7017,4055],{"class":499},[235,7019,1984],{"class":499},[235,7021,7022,7024,7026,7028,7030,7032],{"class":237,"line":815},[235,7023,5747],{"class":495},[235,7025,500],{"class":499},[235,7027,4040],{"class":499},[235,7029,5754],{"class":245},[235,7031,4055],{"class":499},[235,7033,1984],{"class":499},[235,7035,7036,7038,7040],{"class":237,"line":823},[235,7037,4062],{"class":495},[235,7039,500],{"class":499},[235,7041,1385],{"class":519},[235,7043,7044],{"class":237,"line":833},[235,7045,5771],{"class":499},[235,7047,7048,7050,7052,7054,7056,7058],{"class":237,"line":3537},[235,7049,4071],{"class":495},[235,7051,500],{"class":499},[235,7053,503],{"class":499},[235,7055,5782],{"class":245},[235,7057,1345],{"class":499},[235,7059,1984],{"class":499},[235,7061,7062,7064,7066],{"class":237,"line":3542},[235,7063,5791],{"class":495},[235,7065,500],{"class":499},[235,7067,1276],{"class":499},[235,7069,7070,7072,7074,7076],{"class":237,"line":3547},[235,7071,5800],{"class":495},[235,7073,500],{"class":499},[235,7075,5805],{"class":4702},[235,7077,1984],{"class":499},[235,7079,7080],{"class":237,"line":3553},[235,7081,5812],{"class":499},[235,7083,7084],{"class":237,"line":3558},[235,7085,5817],{"class":499},[235,7087,7088],{"class":237,"line":3564},[235,7089,5822],{"class":519},[235,7091,7092],{"class":237,"line":4},[235,7093,2181],{"class":499},[235,7095,7096],{"class":237,"line":3575},[235,7097,1444],{"class":519},[235,7099,7100],{"class":237,"line":3581},[235,7101,263],{"emptyLinePlaceholder":262},[235,7103,7104,7107,7110,7112,7115,7117,7120],{"class":237,"line":3587},[235,7105,7106],{"class":1269},"if",[235,7108,7109],{"class":519},"(process",[235,7111,1694],{"class":499},[235,7113,7114],{"class":519},"env",[235,7116,1694],{"class":499},[235,7118,7119],{"class":519},"es5)",[235,7121,1976],{"class":499},[235,7123,7124,7126,7128,7130],{"class":237,"line":3593},[235,7125,4192],{"class":519},[235,7127,1694],{"class":499},[235,7129,4606],{"class":252},[235,7131,4609],{"class":495},[235,7133,7134],{"class":237,"line":3599},[235,7135,7136],{"class":499},"        {\n",[235,7138,7139,7142,7144,7146,7148,7151,7154,7156,7158,7160],{"class":237,"line":3605},[235,7140,7141],{"class":495},"            test",[235,7143,500],{"class":499},[235,7145,4040],{"class":499},[235,7147,4043],{"class":519},[235,7149,7150],{"class":245},"m",[235,7152,7153],{"class":499},"?",[235,7155,1262],{"class":245},[235,7157,4052],{"class":1269},[235,7159,4055],{"class":499},[235,7161,1984],{"class":499},[235,7163,7164,7167,7169,7172,7174,7176,7179,7182],{"class":237,"line":3611},[235,7165,7166],{"class":495},"            exclude",[235,7168,500],{"class":499},[235,7170,7171],{"class":499}," \u002F(",[235,7173,5754],{"class":245},[235,7175,6729],{"class":499},[235,7177,7178],{"class":245},"bower_components",[235,7180,7181],{"class":499},")\u002F",[235,7183,1984],{"class":499},[235,7185,7186,7189,7191],{"class":237,"line":3616},[235,7187,7188],{"class":495},"            use",[235,7190,500],{"class":499},[235,7192,1276],{"class":499},[235,7194,7195,7198,7200,7202,7205,7207],{"class":237,"line":3621},[235,7196,7197],{"class":495},"              loader",[235,7199,500],{"class":499},[235,7201,503],{"class":499},[235,7203,7204],{"class":245},"babel-loader",[235,7206,1345],{"class":499},[235,7208,1984],{"class":499},[235,7210,7211,7214,7216],{"class":237,"line":3626},[235,7212,7213],{"class":495},"              options",[235,7215,500],{"class":499},[235,7217,1276],{"class":499},[235,7219,7220,7223,7225,7227,7229,7232,7234],{"class":237,"line":3632},[235,7221,7222],{"class":495},"                presets",[235,7224,500],{"class":499},[235,7226,5192],{"class":495},[235,7228,1345],{"class":499},[235,7230,7231],{"class":245},"@babel\u002Fpreset-env",[235,7233,1345],{"class":499},[235,7235,1444],{"class":495},[235,7237,7239],{"class":237,"line":7238},55,[235,7240,7241],{"class":499},"              }\n",[235,7243,7245],{"class":237,"line":7244},56,[235,7246,6828],{"class":499},[235,7248,7250,7253,7255],{"class":237,"line":7249},57,[235,7251,7252],{"class":495},"            generator",[235,7254,500],{"class":499},[235,7256,1276],{"class":499},[235,7258,7260,7263,7265,7267,7270],{"class":237,"line":7259},58,[235,7261,7262],{"class":495},"              filename",[235,7264,500],{"class":499},[235,7266,503],{"class":499},[235,7268,7269],{"class":245},"[name].js",[235,7271,509],{"class":499},[235,7273,7275],{"class":237,"line":7274},59,[235,7276,5812],{"class":499},[235,7278,7280],{"class":237,"line":7279},60,[235,7281,4086],{"class":499},[235,7283,7285],{"class":237,"line":7284},61,[235,7286,4715],{"class":495},[235,7288,7290],{"class":237,"line":7289},62,[235,7291,1317],{"class":499},[235,7293,7295],{"class":237,"line":7294},63,[235,7296,263],{"emptyLinePlaceholder":262},[235,7298,7300,7302,7304,7306],{"class":237,"line":7299},64,[235,7301,1376],{"class":1375},[235,7303,4111],{"class":519},[235,7305,1382],{"class":499},[235,7307,1276],{"class":499},[235,7309,7311,7313,7315,7318,7320,7323,7325,7327],{"class":237,"line":7310},65,[235,7312,4123],{"class":495},[235,7314,500],{"class":499},[235,7316,7317],{"class":519},"[",[235,7319,1345],{"class":499},[235,7321,7322],{"class":245},".\u002Fsrc\u002Findex.js",[235,7324,1345],{"class":499},[235,7326,4585],{"class":519},[235,7328,1984],{"class":499},[235,7330,7332],{"class":237,"line":7331},66,[235,7333,4139],{"class":519},[235,7335,7337,7339,7341,7344,7346,7348,7350,7352],{"class":237,"line":7336},67,[235,7338,4144],{"class":495},[235,7340,500],{"class":499},[235,7342,7343],{"class":519},"process",[235,7345,1694],{"class":499},[235,7347,7114],{"class":519},[235,7349,1694],{"class":499},[235,7351,1933],{"class":519},[235,7353,1984],{"class":499},[235,7355,7357],{"class":237,"line":7356},68,[235,7358,4160],{"class":519},[235,7360,7362,7364,7366],{"class":237,"line":7361},69,[235,7363,4165],{"class":495},[235,7365,500],{"class":499},[235,7367,1276],{"class":499},[235,7369,7371,7373,7375],{"class":237,"line":7370},70,[235,7372,4174],{"class":495},[235,7374,500],{"class":499},[235,7376,4179],{"class":519},[235,7378,7380],{"class":237,"line":7379},71,[235,7381,4091],{"class":499},[235,7383,7385,7387],{"class":237,"line":7384},72,[235,7386,2127],{"class":495},[235,7388,5182],{"class":499},[235,7390,7392,7394,7396,7398,7400,7402,7404,7406,7408,7410,7412,7414,7416,7418,7420,7422,7424,7426,7428,7430],{"class":237,"line":7391},73,[235,7393,5187],{"class":495},[235,7395,500],{"class":499},[235,7397,5192],{"class":519},[235,7399,1345],{"class":499},[235,7401,5197],{"class":245},[235,7403,1345],{"class":499},[235,7405,1404],{"class":499},[235,7407,503],{"class":499},[235,7409,5206],{"class":245},[235,7411,1345],{"class":499},[235,7413,1404],{"class":499},[235,7415,503],{"class":499},[235,7417,5215],{"class":245},[235,7419,1345],{"class":499},[235,7421,1404],{"class":499},[235,7423,503],{"class":499},[235,7425,5224],{"class":245},[235,7427,1345],{"class":499},[235,7429,4585],{"class":519},[235,7431,1984],{"class":499},[235,7433,7435,7437,7439],{"class":237,"line":7434},74,[235,7436,5235],{"class":495},[235,7438,500],{"class":499},[235,7440,1276],{"class":499},[235,7442,7444,7447,7449,7451,7453,7455,7457,7459,7461,7463,7465,7467,7469,7471],{"class":237,"line":7443},75,[235,7445,7446],{"class":499},"          '",[235,7448,5247],{"class":495},[235,7450,1345],{"class":499},[235,7452,500],{"class":499},[235,7454,1393],{"class":519},[235,7456,1694],{"class":499},[235,7458,2158],{"class":252},[235,7460,4640],{"class":519},[235,7462,1404],{"class":499},[235,7464,503],{"class":499},[235,7466,3925],{"class":245},[235,7468,1345],{"class":499},[235,7470,1715],{"class":519},[235,7472,1984],{"class":499},[235,7474,7476],{"class":237,"line":7475},76,[235,7477,5276],{"class":499},[235,7479,7481,7483,7485,7487,7489,7491,7493,7495,7497,7499,7501,7503],{"class":237,"line":7480},77,[235,7482,5286],{"class":495},[235,7484,500],{"class":499},[235,7486,5291],{"class":519},[235,7488,1694],{"class":499},[235,7490,2158],{"class":252},[235,7492,4640],{"class":519},[235,7494,1404],{"class":499},[235,7496,595],{"class":499},[235,7498,3925],{"class":245},[235,7500,1517],{"class":499},[235,7502,5308],{"class":519},[235,7504,1984],{"class":499},[235,7506,7508],{"class":237,"line":7507},78,[235,7509,4091],{"class":499},[235,7511,7513],{"class":237,"line":7512},79,[235,7514,7515],{"class":3119},"    \u002F\u002F ファイルの出力設定\n",[235,7517,7519,7522,7524],{"class":237,"line":7518},80,[235,7520,7521],{"class":495},"    output",[235,7523,500],{"class":499},[235,7525,1276],{"class":499},[235,7527,7529],{"class":237,"line":7528},81,[235,7530,7531],{"class":3119},"        \u002F\u002F  出力ファイルのディレクトリ名\n",[235,7533,7535,7538,7540,7542,7545,7547,7550,7553],{"class":237,"line":7534},82,[235,7536,7537],{"class":495},"        path",[235,7539,500],{"class":499},[235,7541,4631],{"class":499},[235,7543,7544],{"class":519},"__dirname",[235,7546,1950],{"class":499},[235,7548,7549],{"class":245},"\u002Fdist",[235,7551,7552],{"class":499},"`",[235,7554,1984],{"class":499},[235,7556,7558,7560,7562,7564,7566,7568],{"class":237,"line":7557},83,[235,7559,4626],{"class":495},[235,7561,500],{"class":499},[235,7563,503],{"class":499},[235,7565,7269],{"class":245},[235,7567,1345],{"class":499},[235,7569,1984],{"class":499},[235,7571,7573],{"class":237,"line":7572},84,[235,7574,4091],{"class":499},[235,7576,7578,7581,7583],{"class":237,"line":7577},85,[235,7579,7580],{"class":495},"    plugins",[235,7582,500],{"class":499},[235,7584,1385],{"class":519},[235,7586,7588,7591,7594,7596],{"class":237,"line":7587},86,[235,7589,7590],{"class":499},"        new",[235,7592,7593],{"class":252}," MiniCssExtractPlugin",[235,7595,1705],{"class":519},[235,7597,1976],{"class":499},[235,7599,7601,7603,7605,7607,7610],{"class":237,"line":7600},87,[235,7602,6909],{"class":495},[235,7604,500],{"class":499},[235,7606,503],{"class":499},[235,7608,7609],{"class":245},"[name].css",[235,7611,509],{"class":499},[235,7613,7615,7618,7620],{"class":237,"line":7614},88,[235,7616,7617],{"class":499},"        }",[235,7619,1715],{"class":519},[235,7621,1984],{"class":499},[235,7623,7625],{"class":237,"line":7624},89,[235,7626,7627],{"class":519},"    ]\n",[235,7629,7631],{"class":237,"line":7630},90,[235,7632,7633],{"class":499},"};\n",[235,7635,7637],{"class":237,"line":7636},91,[235,7638,263],{"emptyLinePlaceholder":262},[235,7640,7642,7644,7646,7648,7650,7652,7654,7656,7658,7660,7662,7664],{"class":237,"line":7641},92,[235,7643,1376],{"class":1375},[235,7645,6185],{"class":519},[235,7647,1382],{"class":499},[235,7649,4488],{"class":519},[235,7651,1694],{"class":499},[235,7653,4493],{"class":252},[235,7655,1705],{"class":519},[235,7657,1345],{"class":499},[235,7659,6492],{"class":245},[235,7661,1345],{"class":499},[235,7663,1404],{"class":499},[235,7665,1276],{"class":499},[235,7667,7669,7671,7673,7675,7677,7679,7681,7683,7685,7687,7689],{"class":237,"line":7668},93,[235,7670,6211],{"class":495},[235,7672,500],{"class":499},[235,7674,6216],{"class":519},[235,7676,1345],{"class":499},[235,7678,6221],{"class":245},[235,7680,1345],{"class":499},[235,7682,1404],{"class":499},[235,7684,1345],{"class":499},[235,7686,6230],{"class":245},[235,7688,1345],{"class":499},[235,7690,6235],{"class":519},[235,7692,7694,7696,7698],{"class":237,"line":7693},94,[235,7695,1950],{"class":499},[235,7697,1715],{"class":519},[235,7699,1348],{"class":499},[235,7701,7703],{"class":237,"line":7702},95,[235,7704,263],{"emptyLinePlaceholder":262},[235,7706,7708,7710,7712,7714,7716,7718,7720,7722,7724],{"class":237,"line":7707},96,[235,7709,6252],{"class":519},[235,7711,1694],{"class":499},[235,7713,4520],{"class":252},[235,7715,1705],{"class":519},[235,7717,1705],{"class":499},[235,7719,5414],{"class":4527},[235,7721,1715],{"class":499},[235,7723,4533],{"class":1375},[235,7725,1276],{"class":499},[235,7727,7729,7731,7733,7735,7737,7739,7741,7743,7745,7747,7749,7751,7753,7755,7757,7759,7761,7763,7765,7767,7769,7771,7773,7775,7777,7779,7781,7783,7785,7787,7789],{"class":237,"line":7728},97,[235,7730,4540],{"class":1375},[235,7732,6275],{"class":519},[235,7734,4116],{"class":499},[235,7736,6280],{"class":519},[235,7738,1694],{"class":499},[235,7740,4553],{"class":252},[235,7742,1705],{"class":495},[235,7744,1345],{"class":499},[235,7746,4055],{"class":245},[235,7748,1345],{"class":499},[235,7750,1715],{"class":495},[235,7752,1694],{"class":499},[235,7754,4568],{"class":252},[235,7756,1705],{"class":495},[235,7758,4573],{"class":499},[235,7760,4576],{"class":2836},[235,7762,4579],{"class":495},[235,7764,4582],{"class":2836},[235,7766,4585],{"class":495},[235,7768,1694],{"class":499},[235,7770,6315],{"class":252},[235,7772,1705],{"class":495},[235,7774,1345],{"class":499},[235,7776,6322],{"class":245},[235,7778,1345],{"class":499},[235,7780,1404],{"class":499},[235,7782,503],{"class":499},[235,7784,6331],{"class":245},[235,7786,1345],{"class":499},[235,7788,1715],{"class":495},[235,7790,1348],{"class":499},[235,7792,7794,7796,7798,7800,7802,7804],{"class":237,"line":7793},98,[235,7795,4596],{"class":519},[235,7797,1694],{"class":499},[235,7799,4601],{"class":519},[235,7801,1694],{"class":499},[235,7803,4606],{"class":252},[235,7805,4609],{"class":495},[235,7807,7809,7811,7813,7815],{"class":237,"line":7808},99,[235,7810,4614],{"class":499},[235,7812,4617],{"class":252},[235,7814,1705],{"class":495},[235,7816,1976],{"class":499},[235,7818,7820,7822,7824,7826,7828,7830,7832,7834,7836,7838,7840,7842,7844,7846,7848,7850,7852,7854],{"class":237,"line":7819},100,[235,7821,4626],{"class":495},[235,7823,500],{"class":499},[235,7825,4631],{"class":499},[235,7827,2098],{"class":519},[235,7829,1694],{"class":499},[235,7831,2158],{"class":252},[235,7833,4640],{"class":519},[235,7835,1404],{"class":499},[235,7837,503],{"class":499},[235,7839,3921],{"class":245},[235,7841,1345],{"class":499},[235,7843,1715],{"class":519},[235,7845,1950],{"class":499},[235,7847,4055],{"class":245},[235,7849,4657],{"class":499},[235,7851,3947],{"class":519},[235,7853,4663],{"class":499},[235,7855,1984],{"class":499},[235,7857,7859,7861,7863,7865,7867,7869],{"class":237,"line":7858},101,[235,7860,4670],{"class":495},[235,7862,500],{"class":499},[235,7864,1345],{"class":499},[235,7866,4677],{"class":245},[235,7868,1345],{"class":499},[235,7870,1984],{"class":499},[235,7872,7874,7876,7878,7880],{"class":237,"line":7873},102,[235,7875,4686],{"class":495},[235,7877,500],{"class":499},[235,7879,6280],{"class":519},[235,7881,1984],{"class":499},[235,7883,7885,7887,7889],{"class":237,"line":7884},103,[235,7886,4697],{"class":495},[235,7888,500],{"class":499},[235,7890,4703],{"class":4702},[235,7892,7894,7896],{"class":237,"line":7893},104,[235,7895,4708],{"class":499},[235,7897,1953],{"class":495},[235,7899,7901],{"class":237,"line":7900},105,[235,7902,4715],{"class":495},[235,7904,7906,7908,7910],{"class":237,"line":7905},106,[235,7907,1950],{"class":499},[235,7909,1715],{"class":519},[235,7911,1348],{"class":499},[235,7913,7915],{"class":237,"line":7914},107,[235,7916,263],{"emptyLinePlaceholder":262},[235,7918,7920,7922,7924,7926],{"class":237,"line":7919},108,[235,7921,4220],{"class":499},[235,7923,4116],{"class":499},[235,7925,4225],{"class":519},[235,7927,1348],{"class":499},[2399,7929,7930],{},"html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sbqyR, html code.shiki .sbqyR{--shiki-default:#FF9CAC}",{"title":231,"searchDepth":259,"depth":259,"links":7932},[7933,7934,7940,7946],{"id":3909,"depth":249,"text":3910},{"id":3932,"depth":249,"text":3933,"children":7935},[7936,7937,7938,7939],{"id":3961,"depth":259,"text":3961},{"id":3980,"depth":259,"text":3980},{"id":4230,"depth":259,"text":4230},{"id":5040,"depth":259,"text":5040},{"id":5392,"depth":249,"text":5393,"children":7941},[7942,7943,7944,7945],{"id":5402,"depth":259,"text":5402},{"id":5618,"depth":259,"text":5618},{"id":5669,"depth":259,"text":5669},{"id":6548,"depth":259,"text":6548},{"id":6593,"depth":249,"text":6594},[2427],"2021-10-30","HTMLファイルの取り扱いとPUGを使い方",{},"\u002Fseries\u002Fwell-study-webpack-3",{"title":3882,"description":7949},"well-study-webpack","ちゃんと理解するWebpack5。","series\u002Fwell-study-webpack-3",[1262,7957,3947],"webpack","_mix\u002Flogo-on-white-bg-768x299.png","EsG5Dg5_6qbSZmEa8Ezu5AMWNTpxDesebmF7q4Bkix4",{"id":7961,"title":7962,"body":7963,"category":12230,"createdAt":12231,"description":7962,"extension":2430,"index":2439,"meta":12232,"navigation":262,"path":12233,"publish":262,"seo":12234,"series":2439,"seriesTitle":2439,"stem":12235,"tag":12236,"thumbnail":12237,"updatedAt":2439,"__hash__":12238},"articles\u002Farticles\u002Fpinterest-like-style.md","ピンタレストみたいなカードスタイルで動的に要素を追加する方法",{"type":10,"value":7964,"toc":12211},[7965,7968,7971,7974,7977,7986,7989,7992,8153,8170,8173,8667,8671,8675,8678,8689,8693,8709,8713,8720,8723,8726,8729,8732,8735,9042,9049,9052,9055,9059,9062,9334,9339,9342,9349,10803,10806,10824,10827,10830,11114,11120,11123,11604,11617,11620,11667,11670,11673,12060,12073,12076,12195,12198,12201,12208],[13,7966,7967],{},"こんにちはjunです。突然ですがPinterest（ピンタレスト）ってご存知ですが、以下のような感じのスタイルで画像や動画が一覧で検索できるサービスです。",[183,7969],{":src":7970,":width":3011},"'pinterest-like-style\u002Fpinterest.png'",[13,7972,7973],{},"よくある一覧系のレイアウトは基本的に列と高さを揃えた規則的な物が多い中、ピンタレストは高さが変則であり縦方向に詰めるレイアウトになっています。",[13,7975,7976],{},"ごちゃごちゃとした感じですが、コンテンツがいっぱいあって無駄がないスタイルが好きです。私が関わったあるプロジェクトでこのデザインをやろうとしましたがそこそこ難しかったです。バックから情報を取ってくる仕様だったため、動的に要素を追加してくことを前提として実装の解説をしていきます。コード自体の説明は「実装方法」から行います。",[13,7978,7979,7980,7985],{},"また完成したデモは",[197,7981,7984],{"href":7982,"rel":7983},"https:\u002F\u002Fapps.jun-app.com\u002Fpinterestlike\u002F",[201],"こちら","にあります。",[74,7987,7988],{"id":7988},"構造",[13,7990,7991],{},"構造は以下の通りとします。",[226,7993,7995],{"className":5051,"code":7994,"language":3947,"meta":231,"style":231},"\u003Cdiv class=\"p-cards-render\" id=\"card-container\">\n    \u003Cdiv class=\"c-card-container u-animate\">\n        \u003Cimg src=\".\u002Fred.png\" class=\"c-card-img\">\n    \u003C\u002Fdiv>\n    \u003Cdiv class=\"c-card-container u-animate\">\n        \u003Cimg src=\".\u002Fred.png\" class=\"c-card-img\">\n    \u003C\u002Fdiv>\n    \u003C!-- c-card-containerが基本コンポーネント -->\n\u003C\u002Fdiv>\n",[39,7996,7997,8029,8048,8078,8086,8104,8132,8140,8145],{"__ignoreMap":231},[235,7998,7999,8001,8003,8006,8008,8010,8013,8015,8018,8020,8022,8025,8027],{"class":237,"line":238},[235,8000,1481],{"class":499},[235,8002,1225],{"class":495},[235,8004,8005],{"class":1375}," class",[235,8007,1382],{"class":499},[235,8009,1517],{"class":499},[235,8011,8012],{"class":245},"p-cards-render",[235,8014,1517],{"class":499},[235,8016,8017],{"class":1375}," id",[235,8019,1382],{"class":499},[235,8021,1517],{"class":499},[235,8023,8024],{"class":245},"card-container",[235,8026,1517],{"class":499},[235,8028,1487],{"class":499},[235,8030,8031,8033,8035,8037,8039,8041,8044,8046],{"class":237,"line":249},[235,8032,1492],{"class":499},[235,8034,1225],{"class":495},[235,8036,8005],{"class":1375},[235,8038,1382],{"class":499},[235,8040,1517],{"class":499},[235,8042,8043],{"class":245},"c-card-container u-animate",[235,8045,1517],{"class":499},[235,8047,1487],{"class":499},[235,8049,8050,8052,8054,8056,8058,8060,8063,8065,8067,8069,8071,8074,8076],{"class":237,"line":259},[235,8051,1506],{"class":499},[235,8053,5066],{"class":495},[235,8055,5069],{"class":1375},[235,8057,1382],{"class":499},[235,8059,1517],{"class":499},[235,8061,8062],{"class":245},".\u002Fred.png",[235,8064,1517],{"class":499},[235,8066,8005],{"class":1375},[235,8068,1382],{"class":499},[235,8070,1517],{"class":499},[235,8072,8073],{"class":245},"c-card-img",[235,8075,1517],{"class":499},[235,8077,1487],{"class":499},[235,8079,8080,8082,8084],{"class":237,"line":266},[235,8081,1539],{"class":499},[235,8083,1225],{"class":495},[235,8085,1487],{"class":499},[235,8087,8088,8090,8092,8094,8096,8098,8100,8102],{"class":237,"line":275},[235,8089,1492],{"class":499},[235,8091,1225],{"class":495},[235,8093,8005],{"class":1375},[235,8095,1382],{"class":499},[235,8097,1517],{"class":499},[235,8099,8043],{"class":245},[235,8101,1517],{"class":499},[235,8103,1487],{"class":499},[235,8105,8106,8108,8110,8112,8114,8116,8118,8120,8122,8124,8126,8128,8130],{"class":237,"line":283},[235,8107,1506],{"class":499},[235,8109,5066],{"class":495},[235,8111,5069],{"class":1375},[235,8113,1382],{"class":499},[235,8115,1517],{"class":499},[235,8117,8062],{"class":245},[235,8119,1517],{"class":499},[235,8121,8005],{"class":1375},[235,8123,1382],{"class":499},[235,8125,1517],{"class":499},[235,8127,8073],{"class":245},[235,8129,1517],{"class":499},[235,8131,1487],{"class":499},[235,8133,8134,8136,8138],{"class":237,"line":291},[235,8135,1539],{"class":499},[235,8137,1225],{"class":495},[235,8139,1487],{"class":499},[235,8141,8142],{"class":237,"line":298},[235,8143,8144],{"class":3119},"    \u003C!-- c-card-containerが基本コンポーネント -->\n",[235,8146,8147,8149,8151],{"class":237,"line":380},[235,8148,1530],{"class":499},[235,8150,1225],{"class":495},[235,8152,1487],{"class":499},[13,8154,8155,8157,8158,8161,8162,8165,8166,8169],{},[39,8156,8024],{},"はカード全体の列を定義するコンテナです。",[39,8159,8160],{},"c-card-container","は１カードのコンテナーで他のカードとの隙間やレイアウトの定義をしています。そしてカードのコンテナには",[39,8163,8164],{},"\u003Cimg>","がラップされ、",[39,8167,8168],{},"width:100%; height:100%;","がかかっています。今回表示する画像は一面一色に塗り潰された画像です。（background-colorでもよかったのですが）",[13,8171,8172],{},"最終的なcssは以下の通りです。",[226,8174,8178],{"className":8175,"code":8176,"language":8177,"meta":231,"style":231},"language-css shiki shiki-themes material-theme-ocean","*{\n    margin: 0;\n    padding: 0;\n    box-sizing: border-box;\n}\n\n#card-add{\n    position: fixed;\n    left: 20px;\n    top: 50%;\n}\n\n.p-main-container{\n    max-width: 660px;\n    margin: 0 auto;\n    padding: 30px 0px;\n    min-height: 100vh;\n}\n\n.p-cards-render{\n    margin: 0 -5px;\n    display: flex;\n    flex-wrap: wrap;\n    position: relative;\n}\n\n.p-cards-render .c-card-container{\n    position: absolute;\n    top: 0px;\n    width: 33.3%;\n    display: block;\n    padding: 0 5px 10px 5px;\n}\n\n\n.c-card-container .c-card-img{\n    width: 100%;\n    box-shadow: 0px 2px 4px #ccc;\n    border-radius: 30px;\n    height: 0%;\n    display: block;\n    opacity: 0;\n    transition: all 0.4s;\n}\n.c-card-container.u-animate .c-card-img{\n    height: 100%;\n    opacity: 1;\n    transition: all 0.4s;\n}\n","css",[39,8179,8180,8187,8200,8211,8223,8227,8231,8241,8253,8265,8277,8281,8285,8294,8306,8319,8333,8345,8349,8353,8361,8374,8386,8398,8409,8413,8417,8430,8441,8451,8463,8474,8492,8496,8500,8504,8516,8527,8550,8561,8573,8583,8594,8609,8613,8630,8640,8651,8663],{"__ignoreMap":231},[235,8181,8182,8185],{"class":237,"line":238},[235,8183,8184],{"class":241},"*",[235,8186,1976],{"class":499},[235,8188,8189,8193,8195,8198],{"class":237,"line":249},[235,8190,8192],{"class":8191},"s6YsC","    margin",[235,8194,500],{"class":499},[235,8196,8197],{"class":2836}," 0",[235,8199,1348],{"class":499},[235,8201,8202,8205,8207,8209],{"class":237,"line":259},[235,8203,8204],{"class":8191},"    padding",[235,8206,500],{"class":499},[235,8208,8197],{"class":2836},[235,8210,1348],{"class":499},[235,8212,8213,8216,8218,8221],{"class":237,"line":266},[235,8214,8215],{"class":8191},"    box-sizing",[235,8217,500],{"class":499},[235,8219,8220],{"class":519}," border-box",[235,8222,1348],{"class":499},[235,8224,8225],{"class":237,"line":275},[235,8226,1317],{"class":499},[235,8228,8229],{"class":237,"line":283},[235,8230,263],{"emptyLinePlaceholder":262},[235,8232,8233,8236,8239],{"class":237,"line":291},[235,8234,8235],{"class":499},"#",[235,8237,8238],{"class":2836},"card-add",[235,8240,1976],{"class":499},[235,8242,8243,8246,8248,8251],{"class":237,"line":298},[235,8244,8245],{"class":8191},"    position",[235,8247,500],{"class":499},[235,8249,8250],{"class":519}," fixed",[235,8252,1348],{"class":499},[235,8254,8255,8258,8260,8263],{"class":237,"line":380},[235,8256,8257],{"class":8191},"    left",[235,8259,500],{"class":499},[235,8261,8262],{"class":2836}," 20px",[235,8264,1348],{"class":499},[235,8266,8267,8270,8272,8275],{"class":237,"line":465},[235,8268,8269],{"class":8191},"    top",[235,8271,500],{"class":499},[235,8273,8274],{"class":2836}," 50%",[235,8276,1348],{"class":499},[235,8278,8279],{"class":237,"line":590},[235,8280,1317],{"class":499},[235,8282,8283],{"class":237,"line":604},[235,8284,263],{"emptyLinePlaceholder":262},[235,8286,8287,8289,8292],{"class":237,"line":612},[235,8288,1694],{"class":499},[235,8290,8291],{"class":241},"p-main-container",[235,8293,1976],{"class":499},[235,8295,8296,8299,8301,8304],{"class":237,"line":623},[235,8297,8298],{"class":8191},"    max-width",[235,8300,500],{"class":499},[235,8302,8303],{"class":2836}," 660px",[235,8305,1348],{"class":499},[235,8307,8308,8310,8312,8314,8317],{"class":237,"line":634},[235,8309,8192],{"class":8191},[235,8311,500],{"class":499},[235,8313,8197],{"class":2836},[235,8315,8316],{"class":519}," auto",[235,8318,1348],{"class":499},[235,8320,8321,8323,8325,8328,8331],{"class":237,"line":641},[235,8322,8204],{"class":8191},[235,8324,500],{"class":499},[235,8326,8327],{"class":2836}," 30px",[235,8329,8330],{"class":2836}," 0px",[235,8332,1348],{"class":499},[235,8334,8335,8338,8340,8343],{"class":237,"line":653},[235,8336,8337],{"class":8191},"    min-height",[235,8339,500],{"class":499},[235,8341,8342],{"class":2836}," 100vh",[235,8344,1348],{"class":499},[235,8346,8347],{"class":237,"line":661},[235,8348,1317],{"class":499},[235,8350,8351],{"class":237,"line":670},[235,8352,263],{"emptyLinePlaceholder":262},[235,8354,8355,8357,8359],{"class":237,"line":678},[235,8356,1694],{"class":499},[235,8358,8012],{"class":241},[235,8360,1976],{"class":499},[235,8362,8363,8365,8367,8369,8372],{"class":237,"line":686},[235,8364,8192],{"class":8191},[235,8366,500],{"class":499},[235,8368,8197],{"class":2836},[235,8370,8371],{"class":2836}," -5px",[235,8373,1348],{"class":499},[235,8375,8376,8379,8381,8384],{"class":237,"line":694},[235,8377,8378],{"class":8191},"    display",[235,8380,500],{"class":499},[235,8382,8383],{"class":519}," flex",[235,8385,1348],{"class":499},[235,8387,8388,8391,8393,8396],{"class":237,"line":702},[235,8389,8390],{"class":8191},"    flex-wrap",[235,8392,500],{"class":499},[235,8394,8395],{"class":519}," wrap",[235,8397,1348],{"class":499},[235,8399,8400,8402,8404,8407],{"class":237,"line":712},[235,8401,8245],{"class":8191},[235,8403,500],{"class":499},[235,8405,8406],{"class":519}," relative",[235,8408,1348],{"class":499},[235,8410,8411],{"class":237,"line":723},[235,8412,1317],{"class":499},[235,8414,8415],{"class":237,"line":730},[235,8416,263],{"emptyLinePlaceholder":262},[235,8418,8419,8421,8423,8426,8428],{"class":237,"line":741},[235,8420,1694],{"class":499},[235,8422,8012],{"class":241},[235,8424,8425],{"class":499}," .",[235,8427,8160],{"class":241},[235,8429,1976],{"class":499},[235,8431,8432,8434,8436,8439],{"class":237,"line":752},[235,8433,8245],{"class":8191},[235,8435,500],{"class":499},[235,8437,8438],{"class":519}," absolute",[235,8440,1348],{"class":499},[235,8442,8443,8445,8447,8449],{"class":237,"line":763},[235,8444,8269],{"class":8191},[235,8446,500],{"class":499},[235,8448,8330],{"class":2836},[235,8450,1348],{"class":499},[235,8452,8453,8456,8458,8461],{"class":237,"line":774},[235,8454,8455],{"class":8191},"    width",[235,8457,500],{"class":499},[235,8459,8460],{"class":2836}," 33.3%",[235,8462,1348],{"class":499},[235,8464,8465,8467,8469,8472],{"class":237,"line":785},[235,8466,8378],{"class":8191},[235,8468,500],{"class":499},[235,8470,8471],{"class":519}," block",[235,8473,1348],{"class":499},[235,8475,8476,8478,8480,8482,8485,8488,8490],{"class":237,"line":794},[235,8477,8204],{"class":8191},[235,8479,500],{"class":499},[235,8481,8197],{"class":2836},[235,8483,8484],{"class":2836}," 5px",[235,8486,8487],{"class":2836}," 10px",[235,8489,8484],{"class":2836},[235,8491,1348],{"class":499},[235,8493,8494],{"class":237,"line":806},[235,8495,1317],{"class":499},[235,8497,8498],{"class":237,"line":815},[235,8499,263],{"emptyLinePlaceholder":262},[235,8501,8502],{"class":237,"line":823},[235,8503,263],{"emptyLinePlaceholder":262},[235,8505,8506,8508,8510,8512,8514],{"class":237,"line":833},[235,8507,1694],{"class":499},[235,8509,8160],{"class":241},[235,8511,8425],{"class":499},[235,8513,8073],{"class":241},[235,8515,1976],{"class":499},[235,8517,8518,8520,8522,8525],{"class":237,"line":3537},[235,8519,8455],{"class":8191},[235,8521,500],{"class":499},[235,8523,8524],{"class":2836}," 100%",[235,8526,1348],{"class":499},[235,8528,8529,8532,8534,8536,8539,8542,8545,8548],{"class":237,"line":3542},[235,8530,8531],{"class":8191},"    box-shadow",[235,8533,500],{"class":499},[235,8535,8330],{"class":2836},[235,8537,8538],{"class":2836}," 2px",[235,8540,8541],{"class":2836}," 4px",[235,8543,8544],{"class":499}," #",[235,8546,8547],{"class":519},"ccc",[235,8549,1348],{"class":499},[235,8551,8552,8555,8557,8559],{"class":237,"line":3547},[235,8553,8554],{"class":8191},"    border-radius",[235,8556,500],{"class":499},[235,8558,8327],{"class":2836},[235,8560,1348],{"class":499},[235,8562,8563,8566,8568,8571],{"class":237,"line":3553},[235,8564,8565],{"class":8191},"    height",[235,8567,500],{"class":499},[235,8569,8570],{"class":2836}," 0%",[235,8572,1348],{"class":499},[235,8574,8575,8577,8579,8581],{"class":237,"line":3558},[235,8576,8378],{"class":8191},[235,8578,500],{"class":499},[235,8580,8471],{"class":519},[235,8582,1348],{"class":499},[235,8584,8585,8588,8590,8592],{"class":237,"line":3564},[235,8586,8587],{"class":8191},"    opacity",[235,8589,500],{"class":499},[235,8591,8197],{"class":2836},[235,8593,1348],{"class":499},[235,8595,8596,8599,8601,8604,8607],{"class":237,"line":4},[235,8597,8598],{"class":8191},"    transition",[235,8600,500],{"class":499},[235,8602,8603],{"class":519}," all ",[235,8605,8606],{"class":2836},"0.4s",[235,8608,1348],{"class":499},[235,8610,8611],{"class":237,"line":3575},[235,8612,1317],{"class":499},[235,8614,8615,8617,8619,8621,8624,8626,8628],{"class":237,"line":3581},[235,8616,1694],{"class":499},[235,8618,8160],{"class":241},[235,8620,1694],{"class":499},[235,8622,8623],{"class":241},"u-animate",[235,8625,8425],{"class":499},[235,8627,8073],{"class":241},[235,8629,1976],{"class":499},[235,8631,8632,8634,8636,8638],{"class":237,"line":3587},[235,8633,8565],{"class":8191},[235,8635,500],{"class":499},[235,8637,8524],{"class":2836},[235,8639,1348],{"class":499},[235,8641,8642,8644,8646,8649],{"class":237,"line":3593},[235,8643,8587],{"class":8191},[235,8645,500],{"class":499},[235,8647,8648],{"class":2836}," 1",[235,8650,1348],{"class":499},[235,8652,8653,8655,8657,8659,8661],{"class":237,"line":3599},[235,8654,8598],{"class":8191},[235,8656,500],{"class":499},[235,8658,8603],{"class":519},[235,8660,8606],{"class":2836},[235,8662,1348],{"class":499},[235,8664,8665],{"class":237,"line":3605},[235,8666,1317],{"class":499},[74,8668,8670],{"id":8669},"表示数が不明な場合cssだけでは不可能だった","表示数が不明な場合CSSだけでは不可能だった",[81,8672,8674],{"id":8673},"flexでいけんじゃね","flexでいけんじゃね...？!",[13,8676,8677],{},"最初はそれぞれの要素にを縦方向に詰められればいいだけだろと思いました。",[13,8679,8680,8681,8684,8685,8688],{},"そのためカードコンテナーを ",[39,8682,8683],{},"display:inline-block;"," にして ",[39,8686,8687],{},"vertical-align:top;","を指定しましたが下図の様になっていしまいます。",[183,8690],{":src":8691,":width":8692,":center":186},"'pinterest-like-style\u002Fdisplay-inline.png'","'300px'",[13,8694,8695,8696,1209,8698,8701,8702,3652,8705,8708],{},"カードコンテナーを ",[39,8697,8683],{},[39,8699,8700],{},"algin-self:flex-start;","を指定しても同様の結果となります。",[39,8703,8704],{},"flex",[39,8706,8707],{},"inline-block","の仕様上仕方ないです。",[81,8710,8712],{"id":8711},"display-gridならいけるが","display gridならいけるが...",[13,8714,8715,8716,8719],{},"flexは縦方向の制御が難しく、ピンタレストの様なスタイルをcssで実現するためには",[39,8717,8718],{},"display:grid;","というグリットレイアウトを指定する必要があります。",[13,8721,8722],{},"今回はGridの説明は省きます。グリットレイアウトは各要素の縦方向の位置を定義できるので、柔軟なレイアウトを実現できます。",[13,8724,8725],{},"しかし、グリットレイアウトは列数、行数、各要素の占有列・行を指定する必要があります。そのため動的に要素を追加する場合はJavascriptで各要素の位置スタイルを調整する必要があります。",[74,8727,8728],{"id":8728},"実装方法",[81,8730,8731],{"id":8731},"概要",[13,8733,8734],{},"それでは実装の概要について解説します。CSS（インラインスタイル）をカード要素に指定します。いろいろ方法はありますが、ピンタレスト公式でも以下の様なスタイルが要素に当てられています。",[226,8736,8738],{"className":5051,"code":8737,"language":3947,"meta":231,"style":231},"\u003Cdiv class=\"p-cards-render\" id=\"card-container\">\n    \u003Cdiv class=\"c-card-container u-animate\" id=\"06p17111s5\" style=\"height:309px; transform:translate(0%,0px);\">\u003C\u002Fdiv>\n    \u003Cdiv class=\"c-card-container u-animate\" id=\"l1dq533ms9g\" style=\"height:246px; transform:translate(100%,0px);\">\u003C\u002Fdiv>\n    \u003Cdiv class=\"c-card-container u-animate\" id=\"k6n2ebd918g\" style=\"height:306px; transform:translate(200%,0px);\">\u003C\u002Fdiv>\n    \u003Cdiv class=\"c-card-container u-animate\" id=\"2j3vvgc373g\" style=\"height:161px; transform:translate(0%,309px);\">\u003C\u002Fdiv>\n    \u003Cdiv class=\"c-card-container u-animate\" id=\"tagrso5m40o\" style=\"height:255px; transform:translate(100%,246px);\">\u003C\u002Fdiv>\n    \u003Cdiv class=\"c-card-container u-animate\" id=\"89opa7i1eng\" style=\"height:288px; transform:translate(200%,306px);\">\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n",[39,8739,8740,8768,8814,8858,8902,8946,8990,9034],{"__ignoreMap":231},[235,8741,8742,8744,8746,8748,8750,8752,8754,8756,8758,8760,8762,8764,8766],{"class":237,"line":238},[235,8743,1481],{"class":499},[235,8745,1225],{"class":495},[235,8747,8005],{"class":1375},[235,8749,1382],{"class":499},[235,8751,1517],{"class":499},[235,8753,8012],{"class":245},[235,8755,1517],{"class":499},[235,8757,8017],{"class":1375},[235,8759,1382],{"class":499},[235,8761,1517],{"class":499},[235,8763,8024],{"class":245},[235,8765,1517],{"class":499},[235,8767,1487],{"class":499},[235,8769,8770,8772,8774,8776,8778,8780,8782,8784,8786,8788,8790,8793,8795,8798,8800,8802,8805,8807,8810,8812],{"class":237,"line":249},[235,8771,1492],{"class":499},[235,8773,1225],{"class":495},[235,8775,8005],{"class":1375},[235,8777,1382],{"class":499},[235,8779,1517],{"class":499},[235,8781,8043],{"class":245},[235,8783,1517],{"class":499},[235,8785,8017],{"class":1375},[235,8787,1382],{"class":499},[235,8789,1517],{"class":499},[235,8791,8792],{"class":245},"06p17111s5",[235,8794,1517],{"class":499},[235,8796,8797],{"class":1375}," style",[235,8799,1382],{"class":499},[235,8801,1517],{"class":499},[235,8803,8804],{"class":245},"height:309px; transform:translate(0%,0px);",[235,8806,1517],{"class":499},[235,8808,8809],{"class":499},">\u003C\u002F",[235,8811,1225],{"class":495},[235,8813,1487],{"class":499},[235,8815,8816,8818,8820,8822,8824,8826,8828,8830,8832,8834,8836,8839,8841,8843,8845,8847,8850,8852,8854,8856],{"class":237,"line":259},[235,8817,1492],{"class":499},[235,8819,1225],{"class":495},[235,8821,8005],{"class":1375},[235,8823,1382],{"class":499},[235,8825,1517],{"class":499},[235,8827,8043],{"class":245},[235,8829,1517],{"class":499},[235,8831,8017],{"class":1375},[235,8833,1382],{"class":499},[235,8835,1517],{"class":499},[235,8837,8838],{"class":245},"l1dq533ms9g",[235,8840,1517],{"class":499},[235,8842,8797],{"class":1375},[235,8844,1382],{"class":499},[235,8846,1517],{"class":499},[235,8848,8849],{"class":245},"height:246px; transform:translate(100%,0px);",[235,8851,1517],{"class":499},[235,8853,8809],{"class":499},[235,8855,1225],{"class":495},[235,8857,1487],{"class":499},[235,8859,8860,8862,8864,8866,8868,8870,8872,8874,8876,8878,8880,8883,8885,8887,8889,8891,8894,8896,8898,8900],{"class":237,"line":266},[235,8861,1492],{"class":499},[235,8863,1225],{"class":495},[235,8865,8005],{"class":1375},[235,8867,1382],{"class":499},[235,8869,1517],{"class":499},[235,8871,8043],{"class":245},[235,8873,1517],{"class":499},[235,8875,8017],{"class":1375},[235,8877,1382],{"class":499},[235,8879,1517],{"class":499},[235,8881,8882],{"class":245},"k6n2ebd918g",[235,8884,1517],{"class":499},[235,8886,8797],{"class":1375},[235,8888,1382],{"class":499},[235,8890,1517],{"class":499},[235,8892,8893],{"class":245},"height:306px; transform:translate(200%,0px);",[235,8895,1517],{"class":499},[235,8897,8809],{"class":499},[235,8899,1225],{"class":495},[235,8901,1487],{"class":499},[235,8903,8904,8906,8908,8910,8912,8914,8916,8918,8920,8922,8924,8927,8929,8931,8933,8935,8938,8940,8942,8944],{"class":237,"line":275},[235,8905,1492],{"class":499},[235,8907,1225],{"class":495},[235,8909,8005],{"class":1375},[235,8911,1382],{"class":499},[235,8913,1517],{"class":499},[235,8915,8043],{"class":245},[235,8917,1517],{"class":499},[235,8919,8017],{"class":1375},[235,8921,1382],{"class":499},[235,8923,1517],{"class":499},[235,8925,8926],{"class":245},"2j3vvgc373g",[235,8928,1517],{"class":499},[235,8930,8797],{"class":1375},[235,8932,1382],{"class":499},[235,8934,1517],{"class":499},[235,8936,8937],{"class":245},"height:161px; transform:translate(0%,309px);",[235,8939,1517],{"class":499},[235,8941,8809],{"class":499},[235,8943,1225],{"class":495},[235,8945,1487],{"class":499},[235,8947,8948,8950,8952,8954,8956,8958,8960,8962,8964,8966,8968,8971,8973,8975,8977,8979,8982,8984,8986,8988],{"class":237,"line":283},[235,8949,1492],{"class":499},[235,8951,1225],{"class":495},[235,8953,8005],{"class":1375},[235,8955,1382],{"class":499},[235,8957,1517],{"class":499},[235,8959,8043],{"class":245},[235,8961,1517],{"class":499},[235,8963,8017],{"class":1375},[235,8965,1382],{"class":499},[235,8967,1517],{"class":499},[235,8969,8970],{"class":245},"tagrso5m40o",[235,8972,1517],{"class":499},[235,8974,8797],{"class":1375},[235,8976,1382],{"class":499},[235,8978,1517],{"class":499},[235,8980,8981],{"class":245},"height:255px; transform:translate(100%,246px);",[235,8983,1517],{"class":499},[235,8985,8809],{"class":499},[235,8987,1225],{"class":495},[235,8989,1487],{"class":499},[235,8991,8992,8994,8996,8998,9000,9002,9004,9006,9008,9010,9012,9015,9017,9019,9021,9023,9026,9028,9030,9032],{"class":237,"line":291},[235,8993,1492],{"class":499},[235,8995,1225],{"class":495},[235,8997,8005],{"class":1375},[235,8999,1382],{"class":499},[235,9001,1517],{"class":499},[235,9003,8043],{"class":245},[235,9005,1517],{"class":499},[235,9007,8017],{"class":1375},[235,9009,1382],{"class":499},[235,9011,1517],{"class":499},[235,9013,9014],{"class":245},"89opa7i1eng",[235,9016,1517],{"class":499},[235,9018,8797],{"class":1375},[235,9020,1382],{"class":499},[235,9022,1517],{"class":499},[235,9024,9025],{"class":245},"height:288px; transform:translate(200%,306px);",[235,9027,1517],{"class":499},[235,9029,8809],{"class":499},[235,9031,1225],{"class":495},[235,9033,1487],{"class":499},[235,9035,9036,9038,9040],{"class":237,"line":298},[235,9037,1530],{"class":499},[235,9039,1225],{"class":495},[235,9041,1487],{"class":499},[13,9043,9044,9045,9048],{},"それぞのコンテナーに対して",[39,9046,9047],{},"height:246px; transform:translate(200%,306px);","というものあります。まず固有の高さを指定し、そしてtransformを使用して位置を変更しています。",[13,9050,9051],{},"要素が追加される度に始点（left:0;,top:0;）から移動させ、位置を指定してあげます。2021年7月時点のCSSではこの様にしないと、数不明・ここの高さが不明な要素に対してピンタレストのようなスタイルを適用することができません。",[13,9053,9054],{},"では次はそれを実装するjavascriptを書いていきます。",[81,9056,9058],{"id":9057},"htmlの前準備","HTMLの前準備",[13,9060,9061],{},"HTMLは以下の様にしておきます。",[226,9063,9065],{"className":5051,"code":9064,"language":3947,"meta":231,"style":231},"\u003C!DOCTYPE html>\n\u003Chtml>\n    \u003Chead>\n        \u003Cmeta charset=\"utf-8\"> \n        \u003Ctitle>Pinterest like Style\u003C\u002Ftitle>\n        \u003Clink rel=\"stylesheet\" href=\".\u002Fstyle.css\">\n    \u003C\u002Fhead>\n    \u003Cbody>\n        \u003Cdiv class=\"p-main-container\">\n            \u003Cdiv class=\"p-cards-render\" id=\"card-container\">\n\n            \u003C\u002Fdiv>\n            \u003Cbutton id='card-add'>ADD!\u003C\u002Fbutton>\n        \u003C\u002Fdiv>\n    \u003C\u002Fbody>\n    \u003Cscript src=\".\u002Fcard.js\" type=\"text\u002Fjavascript\">\u003C\u002Fscript>\n\u003C\u002Fhtml>\n",[39,9066,9067,9079,9087,9096,9119,9137,9170,9178,9186,9204,9233,9237,9246,9274,9283,9291,9326],{"__ignoreMap":231},[235,9068,9069,9072,9075,9077],{"class":237,"line":238},[235,9070,9071],{"class":499},"\u003C!",[235,9073,9074],{"class":495},"DOCTYPE",[235,9076,6275],{"class":1375},[235,9078,1487],{"class":499},[235,9080,9081,9083,9085],{"class":237,"line":249},[235,9082,1481],{"class":499},[235,9084,3947],{"class":495},[235,9086,1487],{"class":499},[235,9088,9089,9091,9094],{"class":237,"line":259},[235,9090,1492],{"class":499},[235,9092,9093],{"class":495},"head",[235,9095,1487],{"class":499},[235,9097,9098,9100,9103,9106,9108,9110,9113,9115,9117],{"class":237,"line":266},[235,9099,1506],{"class":499},[235,9101,9102],{"class":495},"meta",[235,9104,9105],{"class":1375}," charset",[235,9107,1382],{"class":499},[235,9109,1517],{"class":499},[235,9111,9112],{"class":245},"utf-8",[235,9114,1517],{"class":499},[235,9116,1524],{"class":499},[235,9118,520],{"class":519},[235,9120,9121,9123,9126,9128,9131,9133,9135],{"class":237,"line":275},[235,9122,1506],{"class":499},[235,9124,9125],{"class":495},"title",[235,9127,1524],{"class":499},[235,9129,9130],{"class":519},"Pinterest like Style",[235,9132,1530],{"class":499},[235,9134,9125],{"class":495},[235,9136,1487],{"class":499},[235,9138,9139,9141,9144,9147,9149,9151,9154,9156,9159,9161,9163,9166,9168],{"class":237,"line":283},[235,9140,1506],{"class":499},[235,9142,9143],{"class":495},"link",[235,9145,9146],{"class":1375}," rel",[235,9148,1382],{"class":499},[235,9150,1517],{"class":499},[235,9152,9153],{"class":245},"stylesheet",[235,9155,1517],{"class":499},[235,9157,9158],{"class":1375}," href",[235,9160,1382],{"class":499},[235,9162,1517],{"class":499},[235,9164,9165],{"class":245},".\u002Fstyle.css",[235,9167,1517],{"class":499},[235,9169,1487],{"class":499},[235,9171,9172,9174,9176],{"class":237,"line":291},[235,9173,1539],{"class":499},[235,9175,9093],{"class":495},[235,9177,1487],{"class":499},[235,9179,9180,9182,9184],{"class":237,"line":298},[235,9181,1492],{"class":499},[235,9183,4677],{"class":495},[235,9185,1487],{"class":499},[235,9187,9188,9190,9192,9194,9196,9198,9200,9202],{"class":237,"line":380},[235,9189,1506],{"class":499},[235,9191,1225],{"class":495},[235,9193,8005],{"class":1375},[235,9195,1382],{"class":499},[235,9197,1517],{"class":499},[235,9199,8291],{"class":245},[235,9201,1517],{"class":499},[235,9203,1487],{"class":499},[235,9205,9206,9209,9211,9213,9215,9217,9219,9221,9223,9225,9227,9229,9231],{"class":237,"line":465},[235,9207,9208],{"class":499},"            \u003C",[235,9210,1225],{"class":495},[235,9212,8005],{"class":1375},[235,9214,1382],{"class":499},[235,9216,1517],{"class":499},[235,9218,8012],{"class":245},[235,9220,1517],{"class":499},[235,9222,8017],{"class":1375},[235,9224,1382],{"class":499},[235,9226,1517],{"class":499},[235,9228,8024],{"class":245},[235,9230,1517],{"class":499},[235,9232,1487],{"class":499},[235,9234,9235],{"class":237,"line":590},[235,9236,263],{"emptyLinePlaceholder":262},[235,9238,9239,9242,9244],{"class":237,"line":604},[235,9240,9241],{"class":499},"            \u003C\u002F",[235,9243,1225],{"class":495},[235,9245,1487],{"class":499},[235,9247,9248,9250,9253,9255,9257,9259,9261,9263,9265,9268,9270,9272],{"class":237,"line":612},[235,9249,9208],{"class":499},[235,9251,9252],{"class":495},"button",[235,9254,8017],{"class":1375},[235,9256,1382],{"class":499},[235,9258,1345],{"class":499},[235,9260,8238],{"class":245},[235,9262,1345],{"class":499},[235,9264,1524],{"class":499},[235,9266,9267],{"class":519},"ADD!",[235,9269,1530],{"class":499},[235,9271,9252],{"class":495},[235,9273,1487],{"class":499},[235,9275,9276,9279,9281],{"class":237,"line":623},[235,9277,9278],{"class":499},"        \u003C\u002F",[235,9280,1225],{"class":495},[235,9282,1487],{"class":499},[235,9284,9285,9287,9289],{"class":237,"line":634},[235,9286,1539],{"class":499},[235,9288,4677],{"class":495},[235,9290,1487],{"class":499},[235,9292,9293,9295,9297,9299,9301,9303,9306,9308,9311,9313,9315,9318,9320,9322,9324],{"class":237,"line":641},[235,9294,1492],{"class":499},[235,9296,1558],{"class":495},[235,9298,5069],{"class":1375},[235,9300,1382],{"class":499},[235,9302,1517],{"class":499},[235,9304,9305],{"class":245},".\u002Fcard.js",[235,9307,1517],{"class":499},[235,9309,9310],{"class":1375}," type",[235,9312,1382],{"class":499},[235,9314,1517],{"class":499},[235,9316,9317],{"class":245},"text\u002Fjavascript",[235,9319,1517],{"class":499},[235,9321,8809],{"class":499},[235,9323,1558],{"class":495},[235,9325,1487],{"class":499},[235,9327,9328,9330,9332],{"class":237,"line":653},[235,9329,1530],{"class":499},[235,9331,3947],{"class":495},[235,9333,1487],{"class":499},[13,9335,9336,9338],{},[39,9337,8024],{},"にカードが挿入されていきます。ADD！というボタンを押すことで今回はカードが追加されていくことにします。",[81,9340,9341],{"id":9341},"javascriptはこの通り",[13,9343,9344,9345,9348],{},"同じディレクトリに",[39,9346,9347],{},"card.js","をおいておきます。いきなりですが、全て見せます。完成形は以下の通りです。",[226,9350,9352],{"className":3990,"code":9351,"language":3992,"meta":231,"style":231},"\u002F\u002F カード情報を格納\nlet elements = [];\n\n\u002F\u002F カードの初期値\nlet elementInit = {\n    id:undefined,\n    color:undefined,\n    selfHeight:0,\n    y:0\n};\n\n\u002F\u002F 列数\nlet row = 3;\n\n\u002F\u002F 挿入先コンテナ\nconst cardsContainer = document.getElementById('card-container');\n\n\u002F\u002F 追加ボタン\nconst cardsAddBtn = document.getElementById('card-add');\n\n\u002F\u002F　カード高さの最大値と最小値\nconst heightMax = 400;\nconst heightMin = 100;\n\n\u002F\u002F 色のパターンとカード間の隙間（px）\nconst colors = ['red','yellow','green','orange','blue','purple'];\nconst cardGap = 10;\n\n\u002F\u002F 追加ボタンにイベントリスナーを付与\ncardsAddBtn.addEventListener('click',()=>{\n    return onClickAdd();\n})\n\n\u002F\u002F イベントリスナーの内容\nlet onClickAdd = ()=>{\n    let card = createCard();\n    insertCard(card.dom);\n    scanAdd(card.id);\n}\n\n\u002F\u002F カードのDOMを新規作成\nlet createCard = ()=>{\n    let info = {...elementInit};\n\n    \u002F\u002F カードの要素をdivで作成\n    let contain = document.createElement(\"DIV\");\n    contain.setAttribute('class','c-card-container');\n\n    \u002F\u002F IDをランダムに作成、記録\n    let idname = Math.random().toString(32).substring(2);\n    contain.setAttribute('id',idname);\n    info.id = idname;\n\n    \u002F\u002F カードに表示される画像（一色塗り潰し）を設定、記録\n    \u002F\u002F colorsの値と画像名が同じ。\n    let card = document.createElement(\"IMG\");\n    let color = colors[Math.floor(Math.random() * colors.length)];\n    info.color = color;\n\n    \u002F\u002F IMG要素にカラーの画像とクラス名を付与\n    card.setAttribute('src','.\u002F'+color+'.png');\n    card.setAttribute('class','c-card-img');\n\n    \u002F\u002F カードに対して不明な高さを与える\n    info.selfHeight = Math.floor(Math.random()*(heightMax+1-heightMin))+heightMin;\n    \n    \u002F\u002F カードDIVにIMGを追加\n    contain.appendChild(card);\n\n    \u002F\u002F elementsに記録。DOMとIDを返す\n    elements.push(info);\n    return {dom:contain,id:idname};\n}\n\n\u002F\u002F カードコンテナーにカードを追加する\nlet insertCard = (cardDom)=>{\n    cardsContainer.appendChild(cardDom);\n}\n\n\u002F\u002F これが大切\n\u002F\u002F IDで紐づいたDOMに対して高さと位置を決定させる。\nlet scanAdd = (id) =>{\n    \u002F\u002F elementsから対象カードのIDの番号、情報を取得\n    let index = elements.findIndex(ele=>{return ele.id===id});\n    let ele = elements[index]\n\n    \u002F\u002F DOMを取得\n    let dom = document.getElementById(ele.id);\n\n    \u002F\u002F index、つまりカードが何晩目かと列数でx,yの位置を決定する。\n    let height = ele.selfHeight\n    ele.y = (index \u003C row)?height:elements[index - row].y + height;\n    let x = (index%(row)*100) + '%';\n    let y = (index \u003C row)?0:elements[index - row].y;\n    \n    \u002F\u002F 位置をずらすスタイルを適用\n    dom.setAttribute('style',`height:${height}px; transform:translate(${x},${y}px);`)\n\n    \u002F\u002F アニメーション用のスタイルを追加\n    setTimeout(()=>{\n        dom.classList.add('u-animate')\n    },500);\n}\n",[39,9353,9354,9359,9373,9377,9382,9393,9401,9408,9419,9429,9433,9437,9442,9456,9460,9465,9494,9498,9503,9530,9534,9539,9553,9567,9571,9576,9643,9657,9661,9666,9693,9705,9711,9715,9720,9736,9753,9772,9790,9794,9798,9803,9818,9835,9839,9844,9873,9904,9908,9913,9958,9983,9998,10002,10007,10012,10039,10085,10100,10104,10109,10153,10181,10185,10190,10242,10246,10251,10268,10272,10277,10295,10318,10322,10326,10331,10352,10369,10373,10377,10382,10387,10406,10411,10458,10475,10479,10484,10511,10515,10520,10536,10592,10633,10676,10680,10685,10740,10744,10749,10762,10787,10799],{"__ignoreMap":231},[235,9355,9356],{"class":237,"line":238},[235,9357,9358],{"class":3119},"\u002F\u002F カード情報を格納\n",[235,9360,9361,9363,9366,9368,9371],{"class":237,"line":249},[235,9362,4008],{"class":1375},[235,9364,9365],{"class":519}," elements ",[235,9367,1382],{"class":499},[235,9369,9370],{"class":519}," []",[235,9372,1348],{"class":499},[235,9374,9375],{"class":237,"line":259},[235,9376,263],{"emptyLinePlaceholder":262},[235,9378,9379],{"class":237,"line":266},[235,9380,9381],{"class":3119},"\u002F\u002F カードの初期値\n",[235,9383,9384,9386,9389,9391],{"class":237,"line":275},[235,9385,4008],{"class":1375},[235,9387,9388],{"class":519}," elementInit ",[235,9390,1382],{"class":499},[235,9392,1276],{"class":499},[235,9394,9395,9398],{"class":237,"line":283},[235,9396,9397],{"class":495},"    id",[235,9399,9400],{"class":499},":undefined,\n",[235,9402,9403,9406],{"class":237,"line":291},[235,9404,9405],{"class":495},"    color",[235,9407,9400],{"class":499},[235,9409,9410,9413,9415,9417],{"class":237,"line":298},[235,9411,9412],{"class":495},"    selfHeight",[235,9414,500],{"class":499},[235,9416,4582],{"class":2836},[235,9418,1984],{"class":499},[235,9420,9421,9424,9426],{"class":237,"line":380},[235,9422,9423],{"class":495},"    y",[235,9425,500],{"class":499},[235,9427,9428],{"class":2836},"0\n",[235,9430,9431],{"class":237,"line":465},[235,9432,7633],{"class":499},[235,9434,9435],{"class":237,"line":590},[235,9436,263],{"emptyLinePlaceholder":262},[235,9438,9439],{"class":237,"line":604},[235,9440,9441],{"class":3119},"\u002F\u002F 列数\n",[235,9443,9444,9446,9449,9451,9454],{"class":237,"line":612},[235,9445,4008],{"class":1375},[235,9447,9448],{"class":519}," row ",[235,9450,1382],{"class":499},[235,9452,9453],{"class":2836}," 3",[235,9455,1348],{"class":499},[235,9457,9458],{"class":237,"line":623},[235,9459,263],{"emptyLinePlaceholder":262},[235,9461,9462],{"class":237,"line":634},[235,9463,9464],{"class":3119},"\u002F\u002F 挿入先コンテナ\n",[235,9466,9467,9469,9472,9474,9477,9479,9482,9484,9486,9488,9490,9492],{"class":237,"line":641},[235,9468,1376],{"class":1375},[235,9470,9471],{"class":519}," cardsContainer ",[235,9473,1382],{"class":499},[235,9475,9476],{"class":519}," document",[235,9478,1694],{"class":499},[235,9480,9481],{"class":252},"getElementById",[235,9483,1705],{"class":519},[235,9485,1345],{"class":499},[235,9487,8024],{"class":245},[235,9489,1345],{"class":499},[235,9491,1715],{"class":519},[235,9493,1348],{"class":499},[235,9495,9496],{"class":237,"line":653},[235,9497,263],{"emptyLinePlaceholder":262},[235,9499,9500],{"class":237,"line":661},[235,9501,9502],{"class":3119},"\u002F\u002F 追加ボタン\n",[235,9504,9505,9507,9510,9512,9514,9516,9518,9520,9522,9524,9526,9528],{"class":237,"line":670},[235,9506,1376],{"class":1375},[235,9508,9509],{"class":519}," cardsAddBtn ",[235,9511,1382],{"class":499},[235,9513,9476],{"class":519},[235,9515,1694],{"class":499},[235,9517,9481],{"class":252},[235,9519,1705],{"class":519},[235,9521,1345],{"class":499},[235,9523,8238],{"class":245},[235,9525,1345],{"class":499},[235,9527,1715],{"class":519},[235,9529,1348],{"class":499},[235,9531,9532],{"class":237,"line":678},[235,9533,263],{"emptyLinePlaceholder":262},[235,9535,9536],{"class":237,"line":686},[235,9537,9538],{"class":3119},"\u002F\u002F　カード高さの最大値と最小値\n",[235,9540,9541,9543,9546,9548,9551],{"class":237,"line":694},[235,9542,1376],{"class":1375},[235,9544,9545],{"class":519}," heightMax ",[235,9547,1382],{"class":499},[235,9549,9550],{"class":2836}," 400",[235,9552,1348],{"class":499},[235,9554,9555,9557,9560,9562,9565],{"class":237,"line":702},[235,9556,1376],{"class":1375},[235,9558,9559],{"class":519}," heightMin ",[235,9561,1382],{"class":499},[235,9563,9564],{"class":2836}," 100",[235,9566,1348],{"class":499},[235,9568,9569],{"class":237,"line":712},[235,9570,263],{"emptyLinePlaceholder":262},[235,9572,9573],{"class":237,"line":723},[235,9574,9575],{"class":3119},"\u002F\u002F 色のパターンとカード間の隙間（px）\n",[235,9577,9578,9580,9583,9585,9587,9589,9592,9594,9596,9598,9601,9603,9605,9607,9610,9612,9614,9616,9619,9621,9623,9625,9628,9630,9632,9634,9637,9639,9641],{"class":237,"line":730},[235,9579,1376],{"class":1375},[235,9581,9582],{"class":519}," colors ",[235,9584,1382],{"class":499},[235,9586,5192],{"class":519},[235,9588,1345],{"class":499},[235,9590,9591],{"class":245},"red",[235,9593,1345],{"class":499},[235,9595,1404],{"class":499},[235,9597,1345],{"class":499},[235,9599,9600],{"class":245},"yellow",[235,9602,1345],{"class":499},[235,9604,1404],{"class":499},[235,9606,1345],{"class":499},[235,9608,9609],{"class":245},"green",[235,9611,1345],{"class":499},[235,9613,1404],{"class":499},[235,9615,1345],{"class":499},[235,9617,9618],{"class":245},"orange",[235,9620,1345],{"class":499},[235,9622,1404],{"class":499},[235,9624,1345],{"class":499},[235,9626,9627],{"class":245},"blue",[235,9629,1345],{"class":499},[235,9631,1404],{"class":499},[235,9633,1345],{"class":499},[235,9635,9636],{"class":245},"purple",[235,9638,1345],{"class":499},[235,9640,4585],{"class":519},[235,9642,1348],{"class":499},[235,9644,9645,9647,9650,9652,9655],{"class":237,"line":741},[235,9646,1376],{"class":1375},[235,9648,9649],{"class":519}," cardGap ",[235,9651,1382],{"class":499},[235,9653,9654],{"class":2836}," 10",[235,9656,1348],{"class":499},[235,9658,9659],{"class":237,"line":752},[235,9660,263],{"emptyLinePlaceholder":262},[235,9662,9663],{"class":237,"line":763},[235,9664,9665],{"class":3119},"\u002F\u002F 追加ボタンにイベントリスナーを付与\n",[235,9667,9668,9671,9673,9676,9678,9680,9683,9685,9688,9691],{"class":237,"line":774},[235,9669,9670],{"class":519},"cardsAddBtn",[235,9672,1694],{"class":499},[235,9674,9675],{"class":252},"addEventListener",[235,9677,1705],{"class":519},[235,9679,1345],{"class":499},[235,9681,9682],{"class":245},"click",[235,9684,1345],{"class":499},[235,9686,9687],{"class":499},",()",[235,9689,9690],{"class":1375},"=>",[235,9692,1976],{"class":499},[235,9694,9695,9698,9701,9703],{"class":237,"line":785},[235,9696,9697],{"class":1269},"    return",[235,9699,9700],{"class":252}," onClickAdd",[235,9702,2224],{"class":495},[235,9704,1348],{"class":499},[235,9706,9707,9709],{"class":237,"line":794},[235,9708,1950],{"class":499},[235,9710,1953],{"class":519},[235,9712,9713],{"class":237,"line":806},[235,9714,263],{"emptyLinePlaceholder":262},[235,9716,9717],{"class":237,"line":815},[235,9718,9719],{"class":3119},"\u002F\u002F イベントリスナーの内容\n",[235,9721,9722,9724,9727,9729,9732,9734],{"class":237,"line":823},[235,9723,4008],{"class":1375},[235,9725,9726],{"class":519}," onClickAdd ",[235,9728,1382],{"class":499},[235,9730,9731],{"class":499}," ()",[235,9733,9690],{"class":1375},[235,9735,1976],{"class":499},[235,9737,9738,9741,9744,9746,9749,9751],{"class":237,"line":833},[235,9739,9740],{"class":1375},"    let",[235,9742,9743],{"class":519}," card",[235,9745,4116],{"class":499},[235,9747,9748],{"class":252}," createCard",[235,9750,2224],{"class":495},[235,9752,1348],{"class":499},[235,9754,9755,9758,9760,9763,9765,9768,9770],{"class":237,"line":3537},[235,9756,9757],{"class":252},"    insertCard",[235,9759,1705],{"class":495},[235,9761,9762],{"class":519},"card",[235,9764,1694],{"class":499},[235,9766,9767],{"class":519},"dom",[235,9769,1715],{"class":495},[235,9771,1348],{"class":499},[235,9773,9774,9777,9779,9781,9783,9786,9788],{"class":237,"line":3542},[235,9775,9776],{"class":252},"    scanAdd",[235,9778,1705],{"class":495},[235,9780,9762],{"class":519},[235,9782,1694],{"class":499},[235,9784,9785],{"class":519},"id",[235,9787,1715],{"class":495},[235,9789,1348],{"class":499},[235,9791,9792],{"class":237,"line":3547},[235,9793,1317],{"class":499},[235,9795,9796],{"class":237,"line":3553},[235,9797,263],{"emptyLinePlaceholder":262},[235,9799,9800],{"class":237,"line":3558},[235,9801,9802],{"class":3119},"\u002F\u002F カードのDOMを新規作成\n",[235,9804,9805,9807,9810,9812,9814,9816],{"class":237,"line":3564},[235,9806,4008],{"class":1375},[235,9808,9809],{"class":519}," createCard ",[235,9811,1382],{"class":499},[235,9813,9731],{"class":499},[235,9815,9690],{"class":1375},[235,9817,1976],{"class":499},[235,9819,9820,9822,9825,9827,9830,9833],{"class":237,"line":4},[235,9821,9740],{"class":1375},[235,9823,9824],{"class":519}," info",[235,9826,4116],{"class":499},[235,9828,9829],{"class":499}," {...",[235,9831,9832],{"class":519},"elementInit",[235,9834,7633],{"class":499},[235,9836,9837],{"class":237,"line":3575},[235,9838,263],{"emptyLinePlaceholder":262},[235,9840,9841],{"class":237,"line":3581},[235,9842,9843],{"class":3119},"    \u002F\u002F カードの要素をdivで作成\n",[235,9845,9846,9848,9851,9853,9855,9857,9860,9862,9864,9867,9869,9871],{"class":237,"line":3587},[235,9847,9740],{"class":1375},[235,9849,9850],{"class":519}," contain",[235,9852,4116],{"class":499},[235,9854,9476],{"class":519},[235,9856,1694],{"class":499},[235,9858,9859],{"class":252},"createElement",[235,9861,1705],{"class":495},[235,9863,1517],{"class":499},[235,9865,9866],{"class":245},"DIV",[235,9868,1517],{"class":499},[235,9870,1715],{"class":495},[235,9872,1348],{"class":499},[235,9874,9875,9878,9880,9883,9885,9887,9890,9892,9894,9896,9898,9900,9902],{"class":237,"line":3593},[235,9876,9877],{"class":519},"    contain",[235,9879,1694],{"class":499},[235,9881,9882],{"class":252},"setAttribute",[235,9884,1705],{"class":495},[235,9886,1345],{"class":499},[235,9888,9889],{"class":245},"class",[235,9891,1345],{"class":499},[235,9893,1404],{"class":499},[235,9895,1345],{"class":499},[235,9897,8160],{"class":245},[235,9899,1345],{"class":499},[235,9901,1715],{"class":495},[235,9903,1348],{"class":499},[235,9905,9906],{"class":237,"line":3599},[235,9907,263],{"emptyLinePlaceholder":262},[235,9909,9910],{"class":237,"line":3605},[235,9911,9912],{"class":3119},"    \u002F\u002F IDをランダムに作成、記録\n",[235,9914,9915,9917,9920,9922,9925,9927,9930,9932,9934,9937,9939,9942,9944,9946,9949,9951,9954,9956],{"class":237,"line":3611},[235,9916,9740],{"class":1375},[235,9918,9919],{"class":519}," idname",[235,9921,4116],{"class":499},[235,9923,9924],{"class":519}," Math",[235,9926,1694],{"class":499},[235,9928,9929],{"class":252},"random",[235,9931,2224],{"class":495},[235,9933,1694],{"class":499},[235,9935,9936],{"class":252},"toString",[235,9938,1705],{"class":495},[235,9940,9941],{"class":2836},"32",[235,9943,1715],{"class":495},[235,9945,1694],{"class":499},[235,9947,9948],{"class":252},"substring",[235,9950,1705],{"class":495},[235,9952,9953],{"class":2836},"2",[235,9955,1715],{"class":495},[235,9957,1348],{"class":499},[235,9959,9960,9962,9964,9966,9968,9970,9972,9974,9976,9979,9981],{"class":237,"line":3616},[235,9961,9877],{"class":519},[235,9963,1694],{"class":499},[235,9965,9882],{"class":252},[235,9967,1705],{"class":495},[235,9969,1345],{"class":499},[235,9971,9785],{"class":245},[235,9973,1345],{"class":499},[235,9975,1404],{"class":499},[235,9977,9978],{"class":519},"idname",[235,9980,1715],{"class":495},[235,9982,1348],{"class":499},[235,9984,9985,9988,9990,9992,9994,9996],{"class":237,"line":3621},[235,9986,9987],{"class":519},"    info",[235,9989,1694],{"class":499},[235,9991,9785],{"class":519},[235,9993,4116],{"class":499},[235,9995,9919],{"class":519},[235,9997,1348],{"class":499},[235,9999,10000],{"class":237,"line":3626},[235,10001,263],{"emptyLinePlaceholder":262},[235,10003,10004],{"class":237,"line":3632},[235,10005,10006],{"class":3119},"    \u002F\u002F カードに表示される画像（一色塗り潰し）を設定、記録\n",[235,10008,10009],{"class":237,"line":7238},[235,10010,10011],{"class":3119},"    \u002F\u002F colorsの値と画像名が同じ。\n",[235,10013,10014,10016,10018,10020,10022,10024,10026,10028,10030,10033,10035,10037],{"class":237,"line":7244},[235,10015,9740],{"class":1375},[235,10017,9743],{"class":519},[235,10019,4116],{"class":499},[235,10021,9476],{"class":519},[235,10023,1694],{"class":499},[235,10025,9859],{"class":252},[235,10027,1705],{"class":495},[235,10029,1517],{"class":499},[235,10031,10032],{"class":245},"IMG",[235,10034,1517],{"class":499},[235,10036,1715],{"class":495},[235,10038,1348],{"class":499},[235,10040,10041,10043,10046,10048,10051,10053,10056,10058,10061,10063,10065,10067,10069,10072,10074,10076,10078,10081,10083],{"class":237,"line":7249},[235,10042,9740],{"class":1375},[235,10044,10045],{"class":519}," color",[235,10047,4116],{"class":499},[235,10049,10050],{"class":519}," colors",[235,10052,7317],{"class":495},[235,10054,10055],{"class":519},"Math",[235,10057,1694],{"class":499},[235,10059,10060],{"class":252},"floor",[235,10062,1705],{"class":495},[235,10064,10055],{"class":519},[235,10066,1694],{"class":499},[235,10068,9929],{"class":252},[235,10070,10071],{"class":495},"() ",[235,10073,8184],{"class":499},[235,10075,10050],{"class":519},[235,10077,1694],{"class":499},[235,10079,10080],{"class":519},"length",[235,10082,5308],{"class":495},[235,10084,1348],{"class":499},[235,10086,10087,10089,10091,10094,10096,10098],{"class":237,"line":7259},[235,10088,9987],{"class":519},[235,10090,1694],{"class":499},[235,10092,10093],{"class":519},"color",[235,10095,4116],{"class":499},[235,10097,10045],{"class":519},[235,10099,1348],{"class":499},[235,10101,10102],{"class":237,"line":7274},[235,10103,263],{"emptyLinePlaceholder":262},[235,10105,10106],{"class":237,"line":7279},[235,10107,10108],{"class":3119},"    \u002F\u002F IMG要素にカラーの画像とクラス名を付与\n",[235,10110,10111,10114,10116,10118,10120,10122,10124,10126,10128,10130,10133,10135,10138,10140,10142,10144,10147,10149,10151],{"class":237,"line":7284},[235,10112,10113],{"class":519},"    card",[235,10115,1694],{"class":499},[235,10117,9882],{"class":252},[235,10119,1705],{"class":495},[235,10121,1345],{"class":499},[235,10123,3925],{"class":245},[235,10125,1345],{"class":499},[235,10127,1404],{"class":499},[235,10129,1345],{"class":499},[235,10131,10132],{"class":245},".\u002F",[235,10134,1345],{"class":499},[235,10136,10137],{"class":499},"+",[235,10139,10093],{"class":519},[235,10141,10137],{"class":499},[235,10143,1345],{"class":499},[235,10145,10146],{"class":245},".png",[235,10148,1345],{"class":499},[235,10150,1715],{"class":495},[235,10152,1348],{"class":499},[235,10154,10155,10157,10159,10161,10163,10165,10167,10169,10171,10173,10175,10177,10179],{"class":237,"line":7289},[235,10156,10113],{"class":519},[235,10158,1694],{"class":499},[235,10160,9882],{"class":252},[235,10162,1705],{"class":495},[235,10164,1345],{"class":499},[235,10166,9889],{"class":245},[235,10168,1345],{"class":499},[235,10170,1404],{"class":499},[235,10172,1345],{"class":499},[235,10174,8073],{"class":245},[235,10176,1345],{"class":499},[235,10178,1715],{"class":495},[235,10180,1348],{"class":499},[235,10182,10183],{"class":237,"line":7294},[235,10184,263],{"emptyLinePlaceholder":262},[235,10186,10187],{"class":237,"line":7299},[235,10188,10189],{"class":3119},"    \u002F\u002F カードに対して不明な高さを与える\n",[235,10191,10192,10194,10196,10199,10201,10203,10205,10207,10209,10211,10213,10215,10217,10219,10221,10224,10226,10228,10230,10233,10236,10238,10240],{"class":237,"line":7310},[235,10193,9987],{"class":519},[235,10195,1694],{"class":499},[235,10197,10198],{"class":519},"selfHeight",[235,10200,4116],{"class":499},[235,10202,9924],{"class":519},[235,10204,1694],{"class":499},[235,10206,10060],{"class":252},[235,10208,1705],{"class":495},[235,10210,10055],{"class":519},[235,10212,1694],{"class":499},[235,10214,9929],{"class":252},[235,10216,2224],{"class":495},[235,10218,8184],{"class":499},[235,10220,1705],{"class":495},[235,10222,10223],{"class":519},"heightMax",[235,10225,10137],{"class":499},[235,10227,4576],{"class":2836},[235,10229,4573],{"class":499},[235,10231,10232],{"class":519},"heightMin",[235,10234,10235],{"class":495},"))",[235,10237,10137],{"class":499},[235,10239,10232],{"class":519},[235,10241,1348],{"class":499},[235,10243,10244],{"class":237,"line":7331},[235,10245,4160],{"class":495},[235,10247,10248],{"class":237,"line":7336},[235,10249,10250],{"class":3119},"    \u002F\u002F カードDIVにIMGを追加\n",[235,10252,10253,10255,10257,10260,10262,10264,10266],{"class":237,"line":7356},[235,10254,9877],{"class":519},[235,10256,1694],{"class":499},[235,10258,10259],{"class":252},"appendChild",[235,10261,1705],{"class":495},[235,10263,9762],{"class":519},[235,10265,1715],{"class":495},[235,10267,1348],{"class":499},[235,10269,10270],{"class":237,"line":7361},[235,10271,263],{"emptyLinePlaceholder":262},[235,10273,10274],{"class":237,"line":7370},[235,10275,10276],{"class":3119},"    \u002F\u002F elementsに記録。DOMとIDを返す\n",[235,10278,10279,10282,10284,10286,10288,10291,10293],{"class":237,"line":7379},[235,10280,10281],{"class":519},"    elements",[235,10283,1694],{"class":499},[235,10285,4606],{"class":252},[235,10287,1705],{"class":495},[235,10289,10290],{"class":519},"info",[235,10292,1715],{"class":495},[235,10294,1348],{"class":499},[235,10296,10297,10299,10301,10303,10305,10308,10310,10312,10314,10316],{"class":237,"line":7384},[235,10298,9697],{"class":1269},[235,10300,6813],{"class":499},[235,10302,9767],{"class":495},[235,10304,500],{"class":499},[235,10306,10307],{"class":519},"contain",[235,10309,1404],{"class":499},[235,10311,9785],{"class":495},[235,10313,500],{"class":499},[235,10315,9978],{"class":519},[235,10317,7633],{"class":499},[235,10319,10320],{"class":237,"line":7391},[235,10321,1317],{"class":499},[235,10323,10324],{"class":237,"line":7434},[235,10325,263],{"emptyLinePlaceholder":262},[235,10327,10328],{"class":237,"line":7443},[235,10329,10330],{"class":3119},"\u002F\u002F カードコンテナーにカードを追加する\n",[235,10332,10333,10335,10338,10340,10343,10346,10348,10350],{"class":237,"line":7475},[235,10334,4008],{"class":1375},[235,10336,10337],{"class":519}," insertCard ",[235,10339,1382],{"class":499},[235,10341,10342],{"class":499}," (",[235,10344,10345],{"class":4527},"cardDom",[235,10347,1715],{"class":499},[235,10349,9690],{"class":1375},[235,10351,1976],{"class":499},[235,10353,10354,10357,10359,10361,10363,10365,10367],{"class":237,"line":7480},[235,10355,10356],{"class":519},"    cardsContainer",[235,10358,1694],{"class":499},[235,10360,10259],{"class":252},[235,10362,1705],{"class":495},[235,10364,10345],{"class":519},[235,10366,1715],{"class":495},[235,10368,1348],{"class":499},[235,10370,10371],{"class":237,"line":7507},[235,10372,1317],{"class":499},[235,10374,10375],{"class":237,"line":7512},[235,10376,263],{"emptyLinePlaceholder":262},[235,10378,10379],{"class":237,"line":7518},[235,10380,10381],{"class":3119},"\u002F\u002F これが大切\n",[235,10383,10384],{"class":237,"line":7528},[235,10385,10386],{"class":3119},"\u002F\u002F IDで紐づいたDOMに対して高さと位置を決定させる。\n",[235,10388,10389,10391,10394,10396,10398,10400,10402,10404],{"class":237,"line":7534},[235,10390,4008],{"class":1375},[235,10392,10393],{"class":519}," scanAdd ",[235,10395,1382],{"class":499},[235,10397,10342],{"class":499},[235,10399,9785],{"class":4527},[235,10401,1715],{"class":499},[235,10403,4533],{"class":1375},[235,10405,1976],{"class":499},[235,10407,10408],{"class":237,"line":7557},[235,10409,10410],{"class":3119},"    \u002F\u002F elementsから対象カードのIDの番号、情報を取得\n",[235,10412,10413,10415,10418,10420,10423,10425,10428,10430,10433,10435,10437,10440,10443,10445,10447,10450,10452,10454,10456],{"class":237,"line":7572},[235,10414,9740],{"class":1375},[235,10416,10417],{"class":519}," index",[235,10419,4116],{"class":499},[235,10421,10422],{"class":519}," elements",[235,10424,1694],{"class":499},[235,10426,10427],{"class":252},"findIndex",[235,10429,1705],{"class":495},[235,10431,10432],{"class":4527},"ele",[235,10434,9690],{"class":1375},[235,10436,1930],{"class":499},[235,10438,10439],{"class":1269},"return",[235,10441,10442],{"class":519}," ele",[235,10444,1694],{"class":499},[235,10446,9785],{"class":519},[235,10448,10449],{"class":499},"===",[235,10451,9785],{"class":519},[235,10453,1950],{"class":499},[235,10455,1715],{"class":495},[235,10457,1348],{"class":499},[235,10459,10460,10462,10464,10466,10468,10470,10473],{"class":237,"line":7577},[235,10461,9740],{"class":1375},[235,10463,10442],{"class":519},[235,10465,4116],{"class":499},[235,10467,10422],{"class":519},[235,10469,7317],{"class":495},[235,10471,10472],{"class":519},"index",[235,10474,1444],{"class":495},[235,10476,10477],{"class":237,"line":7587},[235,10478,263],{"emptyLinePlaceholder":262},[235,10480,10481],{"class":237,"line":7600},[235,10482,10483],{"class":3119},"    \u002F\u002F DOMを取得\n",[235,10485,10486,10488,10491,10493,10495,10497,10499,10501,10503,10505,10507,10509],{"class":237,"line":7614},[235,10487,9740],{"class":1375},[235,10489,10490],{"class":519}," dom",[235,10492,4116],{"class":499},[235,10494,9476],{"class":519},[235,10496,1694],{"class":499},[235,10498,9481],{"class":252},[235,10500,1705],{"class":495},[235,10502,10432],{"class":519},[235,10504,1694],{"class":499},[235,10506,9785],{"class":519},[235,10508,1715],{"class":495},[235,10510,1348],{"class":499},[235,10512,10513],{"class":237,"line":7624},[235,10514,263],{"emptyLinePlaceholder":262},[235,10516,10517],{"class":237,"line":7630},[235,10518,10519],{"class":3119},"    \u002F\u002F index、つまりカードが何晩目かと列数でx,yの位置を決定する。\n",[235,10521,10522,10524,10527,10529,10531,10533],{"class":237,"line":7636},[235,10523,9740],{"class":1375},[235,10525,10526],{"class":519}," height",[235,10528,4116],{"class":499},[235,10530,10442],{"class":519},[235,10532,1694],{"class":499},[235,10534,10535],{"class":519},"selfHeight\n",[235,10537,10538,10541,10543,10546,10548,10550,10552,10555,10558,10560,10562,10565,10567,10570,10572,10574,10577,10579,10581,10583,10585,10588,10590],{"class":237,"line":7641},[235,10539,10540],{"class":519},"    ele",[235,10542,1694],{"class":499},[235,10544,10545],{"class":519},"y",[235,10547,4116],{"class":499},[235,10549,10342],{"class":495},[235,10551,10472],{"class":519},[235,10553,10554],{"class":499}," \u003C",[235,10556,10557],{"class":519}," row",[235,10559,1715],{"class":495},[235,10561,7153],{"class":499},[235,10563,10564],{"class":519},"height",[235,10566,500],{"class":499},[235,10568,10569],{"class":519},"elements",[235,10571,7317],{"class":495},[235,10573,10472],{"class":519},[235,10575,10576],{"class":499}," -",[235,10578,10557],{"class":519},[235,10580,4585],{"class":495},[235,10582,1694],{"class":499},[235,10584,10545],{"class":519},[235,10586,10587],{"class":499}," +",[235,10589,10526],{"class":519},[235,10591,1348],{"class":499},[235,10593,10594,10596,10599,10601,10603,10605,10608,10610,10613,10615,10617,10620,10623,10625,10627,10629,10631],{"class":237,"line":7668},[235,10595,9740],{"class":1375},[235,10597,10598],{"class":519}," x",[235,10600,4116],{"class":499},[235,10602,10342],{"class":495},[235,10604,10472],{"class":519},[235,10606,10607],{"class":499},"%",[235,10609,1705],{"class":495},[235,10611,10612],{"class":519},"row",[235,10614,1715],{"class":495},[235,10616,8184],{"class":499},[235,10618,10619],{"class":2836},"100",[235,10621,10622],{"class":495},") ",[235,10624,10137],{"class":499},[235,10626,503],{"class":499},[235,10628,10607],{"class":245},[235,10630,1345],{"class":499},[235,10632,1348],{"class":499},[235,10634,10635,10637,10640,10642,10644,10646,10648,10650,10652,10654,10656,10658,10660,10662,10664,10666,10668,10670,10672,10674],{"class":237,"line":7693},[235,10636,9740],{"class":1375},[235,10638,10639],{"class":519}," y",[235,10641,4116],{"class":499},[235,10643,10342],{"class":495},[235,10645,10472],{"class":519},[235,10647,10554],{"class":499},[235,10649,10557],{"class":519},[235,10651,1715],{"class":495},[235,10653,7153],{"class":499},[235,10655,4582],{"class":2836},[235,10657,500],{"class":499},[235,10659,10569],{"class":519},[235,10661,7317],{"class":495},[235,10663,10472],{"class":519},[235,10665,10576],{"class":499},[235,10667,10557],{"class":519},[235,10669,4585],{"class":495},[235,10671,1694],{"class":499},[235,10673,10545],{"class":519},[235,10675,1348],{"class":499},[235,10677,10678],{"class":237,"line":7702},[235,10679,4160],{"class":495},[235,10681,10682],{"class":237,"line":7707},[235,10683,10684],{"class":3119},"    \u002F\u002F 位置をずらすスタイルを適用\n",[235,10686,10687,10690,10692,10694,10696,10698,10700,10702,10704,10706,10709,10711,10713,10715,10718,10720,10723,10725,10727,10729,10731,10733,10736,10738],{"class":237,"line":7728},[235,10688,10689],{"class":519},"    dom",[235,10691,1694],{"class":499},[235,10693,9882],{"class":252},[235,10695,1705],{"class":495},[235,10697,1345],{"class":499},[235,10699,2399],{"class":245},[235,10701,1345],{"class":499},[235,10703,1404],{"class":499},[235,10705,7552],{"class":499},[235,10707,10708],{"class":245},"height:",[235,10710,4657],{"class":499},[235,10712,10564],{"class":519},[235,10714,1950],{"class":499},[235,10716,10717],{"class":245},"px; transform:translate(",[235,10719,4657],{"class":499},[235,10721,10722],{"class":519},"x",[235,10724,1950],{"class":499},[235,10726,1404],{"class":245},[235,10728,4657],{"class":499},[235,10730,10545],{"class":519},[235,10732,1950],{"class":499},[235,10734,10735],{"class":245},"px);",[235,10737,7552],{"class":499},[235,10739,1953],{"class":495},[235,10741,10742],{"class":237,"line":7793},[235,10743,263],{"emptyLinePlaceholder":262},[235,10745,10746],{"class":237,"line":7808},[235,10747,10748],{"class":3119},"    \u002F\u002F アニメーション用のスタイルを追加\n",[235,10750,10751,10754,10756,10758,10760],{"class":237,"line":7819},[235,10752,10753],{"class":252},"    setTimeout",[235,10755,1705],{"class":495},[235,10757,2224],{"class":499},[235,10759,9690],{"class":1375},[235,10761,1976],{"class":499},[235,10763,10764,10767,10769,10772,10774,10777,10779,10781,10783,10785],{"class":237,"line":7858},[235,10765,10766],{"class":519},"        dom",[235,10768,1694],{"class":499},[235,10770,10771],{"class":519},"classList",[235,10773,1694],{"class":499},[235,10775,10776],{"class":252},"add",[235,10778,1705],{"class":495},[235,10780,1345],{"class":499},[235,10782,8623],{"class":245},[235,10784,1345],{"class":499},[235,10786,1953],{"class":495},[235,10788,10789,10792,10795,10797],{"class":237,"line":7873},[235,10790,10791],{"class":499},"    },",[235,10793,10794],{"class":2836},"500",[235,10796,1715],{"class":495},[235,10798,1348],{"class":499},[235,10800,10801],{"class":237,"line":7884},[235,10802,1317],{"class":499},[13,10804,10805],{},"大まかな流れとしては以下の通りです。",[10807,10808,10809,10812,10815,10818,10821],"ol",{},[20,10810,10811],{},"列数、カード座標情報などの初期値と格納する配列の定義。",[20,10813,10814],{},"ボタンに対するイベントリスナーの定義、ボタンを押したら以下を発火。",[20,10816,10817],{},"新しいカードを作成する",[20,10819,10820],{},"カードをコンテナに追加",[20,10822,10823],{},"追加数、列数に応じて追加したカードの位置を決定",[13,10825,10826],{},"それでは細かく解説していきます。",[88,10828,10829],{"id":10829},"定数などの準備",[226,10831,10833],{"className":3990,"code":10832,"language":3992,"meta":231,"style":231},"\u002F\u002F カード情報を格納\nlet elements = [];\n\n\u002F\u002F カードの初期値\nlet elementInit = {\n    id:undefined,\n    color:undefined,\n    selfHeight:0,\n    y:0,\n    x:0\n};\n\n\u002F\u002F 列数\nlet row = 3;\n\n\u002F\u002F 挿入先コンテナ\nconst cardsContainer = document.getElementById('card-container');\n\n\u002F\u002F 追加ボタン\nconst cardsAddBtn = document.getElementById('card-add');\n\n\u002F\u002F　カード高さの最大値と最小値\nconst heightMax = 400;\nconst heightMin = 100;\n\n\u002F\u002F 色のパターンとカード間の隙間（px）\nconst colors = ['red','yellow','green','orange','blue','purple'];\nconst cardGap = 10;\n",[39,10834,10835,10839,10851,10855,10859,10869,10875,10881,10891,10901,10910,10914,10918,10922,10934,10938,10942,10968,10972,10976,11002,11006,11010,11022,11034,11038,11042,11102],{"__ignoreMap":231},[235,10836,10837],{"class":237,"line":238},[235,10838,9358],{"class":3119},[235,10840,10841,10843,10845,10847,10849],{"class":237,"line":249},[235,10842,4008],{"class":1375},[235,10844,9365],{"class":519},[235,10846,1382],{"class":499},[235,10848,9370],{"class":519},[235,10850,1348],{"class":499},[235,10852,10853],{"class":237,"line":259},[235,10854,263],{"emptyLinePlaceholder":262},[235,10856,10857],{"class":237,"line":266},[235,10858,9381],{"class":3119},[235,10860,10861,10863,10865,10867],{"class":237,"line":275},[235,10862,4008],{"class":1375},[235,10864,9388],{"class":519},[235,10866,1382],{"class":499},[235,10868,1276],{"class":499},[235,10870,10871,10873],{"class":237,"line":283},[235,10872,9397],{"class":495},[235,10874,9400],{"class":499},[235,10876,10877,10879],{"class":237,"line":291},[235,10878,9405],{"class":495},[235,10880,9400],{"class":499},[235,10882,10883,10885,10887,10889],{"class":237,"line":298},[235,10884,9412],{"class":495},[235,10886,500],{"class":499},[235,10888,4582],{"class":2836},[235,10890,1984],{"class":499},[235,10892,10893,10895,10897,10899],{"class":237,"line":380},[235,10894,9423],{"class":495},[235,10896,500],{"class":499},[235,10898,4582],{"class":2836},[235,10900,1984],{"class":499},[235,10902,10903,10906,10908],{"class":237,"line":465},[235,10904,10905],{"class":495},"    x",[235,10907,500],{"class":499},[235,10909,9428],{"class":2836},[235,10911,10912],{"class":237,"line":590},[235,10913,7633],{"class":499},[235,10915,10916],{"class":237,"line":604},[235,10917,263],{"emptyLinePlaceholder":262},[235,10919,10920],{"class":237,"line":612},[235,10921,9441],{"class":3119},[235,10923,10924,10926,10928,10930,10932],{"class":237,"line":623},[235,10925,4008],{"class":1375},[235,10927,9448],{"class":519},[235,10929,1382],{"class":499},[235,10931,9453],{"class":2836},[235,10933,1348],{"class":499},[235,10935,10936],{"class":237,"line":634},[235,10937,263],{"emptyLinePlaceholder":262},[235,10939,10940],{"class":237,"line":641},[235,10941,9464],{"class":3119},[235,10943,10944,10946,10948,10950,10952,10954,10956,10958,10960,10962,10964,10966],{"class":237,"line":653},[235,10945,1376],{"class":1375},[235,10947,9471],{"class":519},[235,10949,1382],{"class":499},[235,10951,9476],{"class":519},[235,10953,1694],{"class":499},[235,10955,9481],{"class":252},[235,10957,1705],{"class":519},[235,10959,1345],{"class":499},[235,10961,8024],{"class":245},[235,10963,1345],{"class":499},[235,10965,1715],{"class":519},[235,10967,1348],{"class":499},[235,10969,10970],{"class":237,"line":661},[235,10971,263],{"emptyLinePlaceholder":262},[235,10973,10974],{"class":237,"line":670},[235,10975,9502],{"class":3119},[235,10977,10978,10980,10982,10984,10986,10988,10990,10992,10994,10996,10998,11000],{"class":237,"line":678},[235,10979,1376],{"class":1375},[235,10981,9509],{"class":519},[235,10983,1382],{"class":499},[235,10985,9476],{"class":519},[235,10987,1694],{"class":499},[235,10989,9481],{"class":252},[235,10991,1705],{"class":519},[235,10993,1345],{"class":499},[235,10995,8238],{"class":245},[235,10997,1345],{"class":499},[235,10999,1715],{"class":519},[235,11001,1348],{"class":499},[235,11003,11004],{"class":237,"line":686},[235,11005,263],{"emptyLinePlaceholder":262},[235,11007,11008],{"class":237,"line":694},[235,11009,9538],{"class":3119},[235,11011,11012,11014,11016,11018,11020],{"class":237,"line":702},[235,11013,1376],{"class":1375},[235,11015,9545],{"class":519},[235,11017,1382],{"class":499},[235,11019,9550],{"class":2836},[235,11021,1348],{"class":499},[235,11023,11024,11026,11028,11030,11032],{"class":237,"line":712},[235,11025,1376],{"class":1375},[235,11027,9559],{"class":519},[235,11029,1382],{"class":499},[235,11031,9564],{"class":2836},[235,11033,1348],{"class":499},[235,11035,11036],{"class":237,"line":723},[235,11037,263],{"emptyLinePlaceholder":262},[235,11039,11040],{"class":237,"line":730},[235,11041,9575],{"class":3119},[235,11043,11044,11046,11048,11050,11052,11054,11056,11058,11060,11062,11064,11066,11068,11070,11072,11074,11076,11078,11080,11082,11084,11086,11088,11090,11092,11094,11096,11098,11100],{"class":237,"line":741},[235,11045,1376],{"class":1375},[235,11047,9582],{"class":519},[235,11049,1382],{"class":499},[235,11051,5192],{"class":519},[235,11053,1345],{"class":499},[235,11055,9591],{"class":245},[235,11057,1345],{"class":499},[235,11059,1404],{"class":499},[235,11061,1345],{"class":499},[235,11063,9600],{"class":245},[235,11065,1345],{"class":499},[235,11067,1404],{"class":499},[235,11069,1345],{"class":499},[235,11071,9609],{"class":245},[235,11073,1345],{"class":499},[235,11075,1404],{"class":499},[235,11077,1345],{"class":499},[235,11079,9618],{"class":245},[235,11081,1345],{"class":499},[235,11083,1404],{"class":499},[235,11085,1345],{"class":499},[235,11087,9627],{"class":245},[235,11089,1345],{"class":499},[235,11091,1404],{"class":499},[235,11093,1345],{"class":499},[235,11095,9636],{"class":245},[235,11097,1345],{"class":499},[235,11099,4585],{"class":519},[235,11101,1348],{"class":499},[235,11103,11104,11106,11108,11110,11112],{"class":237,"line":752},[235,11105,1376],{"class":1375},[235,11107,9649],{"class":519},[235,11109,1382],{"class":499},[235,11111,9654],{"class":2836},[235,11113,1348],{"class":499},[13,11115,11116,11117,11119],{},"ここでは追加する際に必要な定数やDOMを定義しておきます。\n",[39,11118,10569],{},"には作成したカードコンテンツを記録しておきます。列＋１番目以降（今回は４番目以降）の高さを調整するときなどに使用します。",[88,11121,11122],{"id":11122},"カードの作成関数を設定",[226,11124,11126],{"className":3990,"code":11125,"language":3992,"meta":231,"style":231},"\u002F\u002F カードのDOMを新規作成\nlet createCard = ()=>{\n    let info = {...elementInit};\n\n    \u002F\u002F カードの要素をdivで作成\n    let contain = document.createElement(\"DIV\");\n    contain.setAttribute('class','c-card-container');\n\n    \u002F\u002F IDをランダムに作成、記録\n    let idname = Math.random().toString(32).substring(2);\n    contain.setAttribute('id',idname);\n    info.id = idname;\n\n    \u002F\u002F カードに表示される画像（一色塗り潰し）を設定、記録\n    \u002F\u002F colorsの値と画像名が同じ。\n    let card = document.createElement(\"IMG\");\n    let color = colors[Math.floor(Math.random() * colors.length)];\n    info.color = color;\n\n    \u002F\u002F IMG要素にカラーの画像とクラス名を付与\n    card.setAttribute('src','.\u002F'+color+'.png');\n    card.setAttribute('class','c-card-img');\n\n    \u002F\u002F カードに対して不明な高さを与える\n    info.selfHeight = Math.floor(Math.random()*(heightMax+1-heightMin))+heightMin;\n    \n    \u002F\u002F カードDIVにIMGを追加\n    contain.appendChild(card);\n\n    \u002F\u002F elementsに記録。DOMとIDを返す\n    elements.push(info);\n    return {dom:contain,id:idname};\n}\n",[39,11127,11128,11132,11146,11160,11164,11168,11194,11222,11226,11230,11268,11292,11306,11310,11314,11318,11344,11384,11398,11402,11406,11446,11474,11478,11482,11530,11534,11538,11554,11558,11562,11578,11600],{"__ignoreMap":231},[235,11129,11130],{"class":237,"line":238},[235,11131,9802],{"class":3119},[235,11133,11134,11136,11138,11140,11142,11144],{"class":237,"line":249},[235,11135,4008],{"class":1375},[235,11137,9809],{"class":519},[235,11139,1382],{"class":499},[235,11141,9731],{"class":499},[235,11143,9690],{"class":1375},[235,11145,1976],{"class":499},[235,11147,11148,11150,11152,11154,11156,11158],{"class":237,"line":259},[235,11149,9740],{"class":1375},[235,11151,9824],{"class":519},[235,11153,4116],{"class":499},[235,11155,9829],{"class":499},[235,11157,9832],{"class":519},[235,11159,7633],{"class":499},[235,11161,11162],{"class":237,"line":266},[235,11163,263],{"emptyLinePlaceholder":262},[235,11165,11166],{"class":237,"line":275},[235,11167,9843],{"class":3119},[235,11169,11170,11172,11174,11176,11178,11180,11182,11184,11186,11188,11190,11192],{"class":237,"line":283},[235,11171,9740],{"class":1375},[235,11173,9850],{"class":519},[235,11175,4116],{"class":499},[235,11177,9476],{"class":519},[235,11179,1694],{"class":499},[235,11181,9859],{"class":252},[235,11183,1705],{"class":495},[235,11185,1517],{"class":499},[235,11187,9866],{"class":245},[235,11189,1517],{"class":499},[235,11191,1715],{"class":495},[235,11193,1348],{"class":499},[235,11195,11196,11198,11200,11202,11204,11206,11208,11210,11212,11214,11216,11218,11220],{"class":237,"line":291},[235,11197,9877],{"class":519},[235,11199,1694],{"class":499},[235,11201,9882],{"class":252},[235,11203,1705],{"class":495},[235,11205,1345],{"class":499},[235,11207,9889],{"class":245},[235,11209,1345],{"class":499},[235,11211,1404],{"class":499},[235,11213,1345],{"class":499},[235,11215,8160],{"class":245},[235,11217,1345],{"class":499},[235,11219,1715],{"class":495},[235,11221,1348],{"class":499},[235,11223,11224],{"class":237,"line":298},[235,11225,263],{"emptyLinePlaceholder":262},[235,11227,11228],{"class":237,"line":380},[235,11229,9912],{"class":3119},[235,11231,11232,11234,11236,11238,11240,11242,11244,11246,11248,11250,11252,11254,11256,11258,11260,11262,11264,11266],{"class":237,"line":465},[235,11233,9740],{"class":1375},[235,11235,9919],{"class":519},[235,11237,4116],{"class":499},[235,11239,9924],{"class":519},[235,11241,1694],{"class":499},[235,11243,9929],{"class":252},[235,11245,2224],{"class":495},[235,11247,1694],{"class":499},[235,11249,9936],{"class":252},[235,11251,1705],{"class":495},[235,11253,9941],{"class":2836},[235,11255,1715],{"class":495},[235,11257,1694],{"class":499},[235,11259,9948],{"class":252},[235,11261,1705],{"class":495},[235,11263,9953],{"class":2836},[235,11265,1715],{"class":495},[235,11267,1348],{"class":499},[235,11269,11270,11272,11274,11276,11278,11280,11282,11284,11286,11288,11290],{"class":237,"line":590},[235,11271,9877],{"class":519},[235,11273,1694],{"class":499},[235,11275,9882],{"class":252},[235,11277,1705],{"class":495},[235,11279,1345],{"class":499},[235,11281,9785],{"class":245},[235,11283,1345],{"class":499},[235,11285,1404],{"class":499},[235,11287,9978],{"class":519},[235,11289,1715],{"class":495},[235,11291,1348],{"class":499},[235,11293,11294,11296,11298,11300,11302,11304],{"class":237,"line":604},[235,11295,9987],{"class":519},[235,11297,1694],{"class":499},[235,11299,9785],{"class":519},[235,11301,4116],{"class":499},[235,11303,9919],{"class":519},[235,11305,1348],{"class":499},[235,11307,11308],{"class":237,"line":612},[235,11309,263],{"emptyLinePlaceholder":262},[235,11311,11312],{"class":237,"line":623},[235,11313,10006],{"class":3119},[235,11315,11316],{"class":237,"line":634},[235,11317,10011],{"class":3119},[235,11319,11320,11322,11324,11326,11328,11330,11332,11334,11336,11338,11340,11342],{"class":237,"line":641},[235,11321,9740],{"class":1375},[235,11323,9743],{"class":519},[235,11325,4116],{"class":499},[235,11327,9476],{"class":519},[235,11329,1694],{"class":499},[235,11331,9859],{"class":252},[235,11333,1705],{"class":495},[235,11335,1517],{"class":499},[235,11337,10032],{"class":245},[235,11339,1517],{"class":499},[235,11341,1715],{"class":495},[235,11343,1348],{"class":499},[235,11345,11346,11348,11350,11352,11354,11356,11358,11360,11362,11364,11366,11368,11370,11372,11374,11376,11378,11380,11382],{"class":237,"line":653},[235,11347,9740],{"class":1375},[235,11349,10045],{"class":519},[235,11351,4116],{"class":499},[235,11353,10050],{"class":519},[235,11355,7317],{"class":495},[235,11357,10055],{"class":519},[235,11359,1694],{"class":499},[235,11361,10060],{"class":252},[235,11363,1705],{"class":495},[235,11365,10055],{"class":519},[235,11367,1694],{"class":499},[235,11369,9929],{"class":252},[235,11371,10071],{"class":495},[235,11373,8184],{"class":499},[235,11375,10050],{"class":519},[235,11377,1694],{"class":499},[235,11379,10080],{"class":519},[235,11381,5308],{"class":495},[235,11383,1348],{"class":499},[235,11385,11386,11388,11390,11392,11394,11396],{"class":237,"line":661},[235,11387,9987],{"class":519},[235,11389,1694],{"class":499},[235,11391,10093],{"class":519},[235,11393,4116],{"class":499},[235,11395,10045],{"class":519},[235,11397,1348],{"class":499},[235,11399,11400],{"class":237,"line":670},[235,11401,263],{"emptyLinePlaceholder":262},[235,11403,11404],{"class":237,"line":678},[235,11405,10108],{"class":3119},[235,11407,11408,11410,11412,11414,11416,11418,11420,11422,11424,11426,11428,11430,11432,11434,11436,11438,11440,11442,11444],{"class":237,"line":686},[235,11409,10113],{"class":519},[235,11411,1694],{"class":499},[235,11413,9882],{"class":252},[235,11415,1705],{"class":495},[235,11417,1345],{"class":499},[235,11419,3925],{"class":245},[235,11421,1345],{"class":499},[235,11423,1404],{"class":499},[235,11425,1345],{"class":499},[235,11427,10132],{"class":245},[235,11429,1345],{"class":499},[235,11431,10137],{"class":499},[235,11433,10093],{"class":519},[235,11435,10137],{"class":499},[235,11437,1345],{"class":499},[235,11439,10146],{"class":245},[235,11441,1345],{"class":499},[235,11443,1715],{"class":495},[235,11445,1348],{"class":499},[235,11447,11448,11450,11452,11454,11456,11458,11460,11462,11464,11466,11468,11470,11472],{"class":237,"line":694},[235,11449,10113],{"class":519},[235,11451,1694],{"class":499},[235,11453,9882],{"class":252},[235,11455,1705],{"class":495},[235,11457,1345],{"class":499},[235,11459,9889],{"class":245},[235,11461,1345],{"class":499},[235,11463,1404],{"class":499},[235,11465,1345],{"class":499},[235,11467,8073],{"class":245},[235,11469,1345],{"class":499},[235,11471,1715],{"class":495},[235,11473,1348],{"class":499},[235,11475,11476],{"class":237,"line":702},[235,11477,263],{"emptyLinePlaceholder":262},[235,11479,11480],{"class":237,"line":712},[235,11481,10189],{"class":3119},[235,11483,11484,11486,11488,11490,11492,11494,11496,11498,11500,11502,11504,11506,11508,11510,11512,11514,11516,11518,11520,11522,11524,11526,11528],{"class":237,"line":723},[235,11485,9987],{"class":519},[235,11487,1694],{"class":499},[235,11489,10198],{"class":519},[235,11491,4116],{"class":499},[235,11493,9924],{"class":519},[235,11495,1694],{"class":499},[235,11497,10060],{"class":252},[235,11499,1705],{"class":495},[235,11501,10055],{"class":519},[235,11503,1694],{"class":499},[235,11505,9929],{"class":252},[235,11507,2224],{"class":495},[235,11509,8184],{"class":499},[235,11511,1705],{"class":495},[235,11513,10223],{"class":519},[235,11515,10137],{"class":499},[235,11517,4576],{"class":2836},[235,11519,4573],{"class":499},[235,11521,10232],{"class":519},[235,11523,10235],{"class":495},[235,11525,10137],{"class":499},[235,11527,10232],{"class":519},[235,11529,1348],{"class":499},[235,11531,11532],{"class":237,"line":730},[235,11533,4160],{"class":495},[235,11535,11536],{"class":237,"line":741},[235,11537,10250],{"class":3119},[235,11539,11540,11542,11544,11546,11548,11550,11552],{"class":237,"line":752},[235,11541,9877],{"class":519},[235,11543,1694],{"class":499},[235,11545,10259],{"class":252},[235,11547,1705],{"class":495},[235,11549,9762],{"class":519},[235,11551,1715],{"class":495},[235,11553,1348],{"class":499},[235,11555,11556],{"class":237,"line":763},[235,11557,263],{"emptyLinePlaceholder":262},[235,11559,11560],{"class":237,"line":774},[235,11561,10276],{"class":3119},[235,11563,11564,11566,11568,11570,11572,11574,11576],{"class":237,"line":785},[235,11565,10281],{"class":519},[235,11567,1694],{"class":499},[235,11569,4606],{"class":252},[235,11571,1705],{"class":495},[235,11573,10290],{"class":519},[235,11575,1715],{"class":495},[235,11577,1348],{"class":499},[235,11579,11580,11582,11584,11586,11588,11590,11592,11594,11596,11598],{"class":237,"line":794},[235,11581,9697],{"class":1269},[235,11583,6813],{"class":499},[235,11585,9767],{"class":495},[235,11587,500],{"class":499},[235,11589,10307],{"class":519},[235,11591,1404],{"class":499},[235,11593,9785],{"class":495},[235,11595,500],{"class":499},[235,11597,9978],{"class":519},[235,11599,7633],{"class":499},[235,11601,11602],{"class":237,"line":806},[235,11603,1317],{"class":499},[13,11605,11606,11607,11610,11611,11613,11614,11616],{},"カードの作成関数",[39,11608,11609],{},"createCard()","を作ります。ここはカードの要素を作成して、ランダムなIDを付与します。変数",[39,11612,10290],{},"にはカードの高さ、IDを記録して",[39,11615,10569],{},"に入れておきます。",[88,11618,11619],{"id":11619},"要素の挿入関数を作成",[226,11621,11623],{"className":3990,"code":11622,"language":3992,"meta":231,"style":231},"\u002F\u002F カードコンテナーにカードを追加する\nlet insertCard = (cardDom)=>{\n    cardsContainer.appendChild(cardDom);\n}\n",[39,11624,11625,11629,11647,11663],{"__ignoreMap":231},[235,11626,11627],{"class":237,"line":238},[235,11628,10330],{"class":3119},[235,11630,11631,11633,11635,11637,11639,11641,11643,11645],{"class":237,"line":249},[235,11632,4008],{"class":1375},[235,11634,10337],{"class":519},[235,11636,1382],{"class":499},[235,11638,10342],{"class":499},[235,11640,10345],{"class":4527},[235,11642,1715],{"class":499},[235,11644,9690],{"class":1375},[235,11646,1976],{"class":499},[235,11648,11649,11651,11653,11655,11657,11659,11661],{"class":237,"line":259},[235,11650,10356],{"class":519},[235,11652,1694],{"class":499},[235,11654,10259],{"class":252},[235,11656,1705],{"class":495},[235,11658,10345],{"class":519},[235,11660,1715],{"class":495},[235,11662,1348],{"class":499},[235,11664,11665],{"class":237,"line":266},[235,11666,1317],{"class":499},[13,11668,11669],{},"ここは作成したカードのDOMをカードコンテナに挿入します。",[88,11671,11672],{"id":11672},"挿入されたカードの高さと位置を決定",[226,11674,11676],{"className":3990,"code":11675,"language":3992,"meta":231,"style":231},"\u002F\u002F これが大切\n\u002F\u002F IDで紐づいたDOMに対して高さと位置を決定させる。\nlet scanAdd = (id) =>{\n    \u002F\u002F elementsから対象カードのIDの番号、情報を取得\n    let index = elements.findIndex(ele=>{return ele.id===id});\n    let ele = elements[index]\n\n    \u002F\u002F DOMを取得\n    let dom = document.getElementById(ele.id);\n\n    \u002F\u002F index、つまりカードが何晩目かと列数でx,yの位置を決定する。\n    let height = ele.selfHeight\n    ele.y = (index \u003C row)?height:elements[index - row].y + height;\n    let x = (index%(row)*100) + '%';\n    let y = (index \u003C row)?0:elements[index - row].y;\n    \n    \u002F\u002F 位置をずらすスタイルを適用\n    dom.setAttribute('style',`height:${height}px; transform:translate(${x},${y}px);`)\n\n    \u002F\u002F アニメーション用のスタイルを追加\n    setTimeout(()=>{\n        dom.classList.add('u-animate')\n    },500);\n}\n",[39,11677,11678,11682,11686,11704,11708,11748,11764,11768,11772,11798,11802,11806,11820,11868,11904,11946,11950,11954,12004,12008,12012,12024,12046,12056],{"__ignoreMap":231},[235,11679,11680],{"class":237,"line":238},[235,11681,10381],{"class":3119},[235,11683,11684],{"class":237,"line":249},[235,11685,10386],{"class":3119},[235,11687,11688,11690,11692,11694,11696,11698,11700,11702],{"class":237,"line":259},[235,11689,4008],{"class":1375},[235,11691,10393],{"class":519},[235,11693,1382],{"class":499},[235,11695,10342],{"class":499},[235,11697,9785],{"class":4527},[235,11699,1715],{"class":499},[235,11701,4533],{"class":1375},[235,11703,1976],{"class":499},[235,11705,11706],{"class":237,"line":266},[235,11707,10410],{"class":3119},[235,11709,11710,11712,11714,11716,11718,11720,11722,11724,11726,11728,11730,11732,11734,11736,11738,11740,11742,11744,11746],{"class":237,"line":275},[235,11711,9740],{"class":1375},[235,11713,10417],{"class":519},[235,11715,4116],{"class":499},[235,11717,10422],{"class":519},[235,11719,1694],{"class":499},[235,11721,10427],{"class":252},[235,11723,1705],{"class":495},[235,11725,10432],{"class":4527},[235,11727,9690],{"class":1375},[235,11729,1930],{"class":499},[235,11731,10439],{"class":1269},[235,11733,10442],{"class":519},[235,11735,1694],{"class":499},[235,11737,9785],{"class":519},[235,11739,10449],{"class":499},[235,11741,9785],{"class":519},[235,11743,1950],{"class":499},[235,11745,1715],{"class":495},[235,11747,1348],{"class":499},[235,11749,11750,11752,11754,11756,11758,11760,11762],{"class":237,"line":283},[235,11751,9740],{"class":1375},[235,11753,10442],{"class":519},[235,11755,4116],{"class":499},[235,11757,10422],{"class":519},[235,11759,7317],{"class":495},[235,11761,10472],{"class":519},[235,11763,1444],{"class":495},[235,11765,11766],{"class":237,"line":291},[235,11767,263],{"emptyLinePlaceholder":262},[235,11769,11770],{"class":237,"line":298},[235,11771,10483],{"class":3119},[235,11773,11774,11776,11778,11780,11782,11784,11786,11788,11790,11792,11794,11796],{"class":237,"line":380},[235,11775,9740],{"class":1375},[235,11777,10490],{"class":519},[235,11779,4116],{"class":499},[235,11781,9476],{"class":519},[235,11783,1694],{"class":499},[235,11785,9481],{"class":252},[235,11787,1705],{"class":495},[235,11789,10432],{"class":519},[235,11791,1694],{"class":499},[235,11793,9785],{"class":519},[235,11795,1715],{"class":495},[235,11797,1348],{"class":499},[235,11799,11800],{"class":237,"line":465},[235,11801,263],{"emptyLinePlaceholder":262},[235,11803,11804],{"class":237,"line":590},[235,11805,10519],{"class":3119},[235,11807,11808,11810,11812,11814,11816,11818],{"class":237,"line":604},[235,11809,9740],{"class":1375},[235,11811,10526],{"class":519},[235,11813,4116],{"class":499},[235,11815,10442],{"class":519},[235,11817,1694],{"class":499},[235,11819,10535],{"class":519},[235,11821,11822,11824,11826,11828,11830,11832,11834,11836,11838,11840,11842,11844,11846,11848,11850,11852,11854,11856,11858,11860,11862,11864,11866],{"class":237,"line":612},[235,11823,10540],{"class":519},[235,11825,1694],{"class":499},[235,11827,10545],{"class":519},[235,11829,4116],{"class":499},[235,11831,10342],{"class":495},[235,11833,10472],{"class":519},[235,11835,10554],{"class":499},[235,11837,10557],{"class":519},[235,11839,1715],{"class":495},[235,11841,7153],{"class":499},[235,11843,10564],{"class":519},[235,11845,500],{"class":499},[235,11847,10569],{"class":519},[235,11849,7317],{"class":495},[235,11851,10472],{"class":519},[235,11853,10576],{"class":499},[235,11855,10557],{"class":519},[235,11857,4585],{"class":495},[235,11859,1694],{"class":499},[235,11861,10545],{"class":519},[235,11863,10587],{"class":499},[235,11865,10526],{"class":519},[235,11867,1348],{"class":499},[235,11869,11870,11872,11874,11876,11878,11880,11882,11884,11886,11888,11890,11892,11894,11896,11898,11900,11902],{"class":237,"line":623},[235,11871,9740],{"class":1375},[235,11873,10598],{"class":519},[235,11875,4116],{"class":499},[235,11877,10342],{"class":495},[235,11879,10472],{"class":519},[235,11881,10607],{"class":499},[235,11883,1705],{"class":495},[235,11885,10612],{"class":519},[235,11887,1715],{"class":495},[235,11889,8184],{"class":499},[235,11891,10619],{"class":2836},[235,11893,10622],{"class":495},[235,11895,10137],{"class":499},[235,11897,503],{"class":499},[235,11899,10607],{"class":245},[235,11901,1345],{"class":499},[235,11903,1348],{"class":499},[235,11905,11906,11908,11910,11912,11914,11916,11918,11920,11922,11924,11926,11928,11930,11932,11934,11936,11938,11940,11942,11944],{"class":237,"line":634},[235,11907,9740],{"class":1375},[235,11909,10639],{"class":519},[235,11911,4116],{"class":499},[235,11913,10342],{"class":495},[235,11915,10472],{"class":519},[235,11917,10554],{"class":499},[235,11919,10557],{"class":519},[235,11921,1715],{"class":495},[235,11923,7153],{"class":499},[235,11925,4582],{"class":2836},[235,11927,500],{"class":499},[235,11929,10569],{"class":519},[235,11931,7317],{"class":495},[235,11933,10472],{"class":519},[235,11935,10576],{"class":499},[235,11937,10557],{"class":519},[235,11939,4585],{"class":495},[235,11941,1694],{"class":499},[235,11943,10545],{"class":519},[235,11945,1348],{"class":499},[235,11947,11948],{"class":237,"line":641},[235,11949,4160],{"class":495},[235,11951,11952],{"class":237,"line":653},[235,11953,10684],{"class":3119},[235,11955,11956,11958,11960,11962,11964,11966,11968,11970,11972,11974,11976,11978,11980,11982,11984,11986,11988,11990,11992,11994,11996,11998,12000,12002],{"class":237,"line":661},[235,11957,10689],{"class":519},[235,11959,1694],{"class":499},[235,11961,9882],{"class":252},[235,11963,1705],{"class":495},[235,11965,1345],{"class":499},[235,11967,2399],{"class":245},[235,11969,1345],{"class":499},[235,11971,1404],{"class":499},[235,11973,7552],{"class":499},[235,11975,10708],{"class":245},[235,11977,4657],{"class":499},[235,11979,10564],{"class":519},[235,11981,1950],{"class":499},[235,11983,10717],{"class":245},[235,11985,4657],{"class":499},[235,11987,10722],{"class":519},[235,11989,1950],{"class":499},[235,11991,1404],{"class":245},[235,11993,4657],{"class":499},[235,11995,10545],{"class":519},[235,11997,1950],{"class":499},[235,11999,10735],{"class":245},[235,12001,7552],{"class":499},[235,12003,1953],{"class":495},[235,12005,12006],{"class":237,"line":670},[235,12007,263],{"emptyLinePlaceholder":262},[235,12009,12010],{"class":237,"line":678},[235,12011,10748],{"class":3119},[235,12013,12014,12016,12018,12020,12022],{"class":237,"line":686},[235,12015,10753],{"class":252},[235,12017,1705],{"class":495},[235,12019,2224],{"class":499},[235,12021,9690],{"class":1375},[235,12023,1976],{"class":499},[235,12025,12026,12028,12030,12032,12034,12036,12038,12040,12042,12044],{"class":237,"line":694},[235,12027,10766],{"class":519},[235,12029,1694],{"class":499},[235,12031,10771],{"class":519},[235,12033,1694],{"class":499},[235,12035,10776],{"class":252},[235,12037,1705],{"class":495},[235,12039,1345],{"class":499},[235,12041,8623],{"class":245},[235,12043,1345],{"class":499},[235,12045,1953],{"class":495},[235,12047,12048,12050,12052,12054],{"class":237,"line":702},[235,12049,10791],{"class":499},[235,12051,10794],{"class":2836},[235,12053,1715],{"class":495},[235,12055,1348],{"class":499},[235,12057,12058],{"class":237,"line":712},[235,12059,1317],{"class":499},[13,12061,12062,12065,12066,12068,12069,12072],{},[39,12063,12064],{},"scanAdd()","では対象のID（DOMのID）に基づいて",[39,12067,10569],{},"から高さを設定する対象のカードと、そのカードの１行上のカードの情報を取得します。例えば５番目のカードの場合、２番目のカードの高さを用いてY座標を決定します。この関数ではその情報を元にしてカードに高さを与え、また表示する位置のx,y座標を決定して",[39,12070,12071],{},"translate","の値を決定します。",[88,12074,12075],{"id":12075},"関数の連結とイベントリスナー",[226,12077,12079],{"className":3990,"code":12078,"language":3992,"meta":231,"style":231},"\u002F\u002F 追加ボタンにイベントリスナーを付与\ncardsAddBtn.addEventListener('click',()=>{\n    return onClickAdd();\n})\n\n\u002F\u002F イベントリスナーの内容\nlet onClickAdd = ()=>{\n    let card = createCard();\n    insertCard(card.dom);\n    scanAdd(card.id);\n}\n",[39,12080,12081,12085,12107,12117,12123,12127,12131,12145,12159,12175,12191],{"__ignoreMap":231},[235,12082,12083],{"class":237,"line":238},[235,12084,9665],{"class":3119},[235,12086,12087,12089,12091,12093,12095,12097,12099,12101,12103,12105],{"class":237,"line":249},[235,12088,9670],{"class":519},[235,12090,1694],{"class":499},[235,12092,9675],{"class":252},[235,12094,1705],{"class":519},[235,12096,1345],{"class":499},[235,12098,9682],{"class":245},[235,12100,1345],{"class":499},[235,12102,9687],{"class":499},[235,12104,9690],{"class":1375},[235,12106,1976],{"class":499},[235,12108,12109,12111,12113,12115],{"class":237,"line":259},[235,12110,9697],{"class":1269},[235,12112,9700],{"class":252},[235,12114,2224],{"class":495},[235,12116,1348],{"class":499},[235,12118,12119,12121],{"class":237,"line":266},[235,12120,1950],{"class":499},[235,12122,1953],{"class":519},[235,12124,12125],{"class":237,"line":275},[235,12126,263],{"emptyLinePlaceholder":262},[235,12128,12129],{"class":237,"line":283},[235,12130,9719],{"class":3119},[235,12132,12133,12135,12137,12139,12141,12143],{"class":237,"line":291},[235,12134,4008],{"class":1375},[235,12136,9726],{"class":519},[235,12138,1382],{"class":499},[235,12140,9731],{"class":499},[235,12142,9690],{"class":1375},[235,12144,1976],{"class":499},[235,12146,12147,12149,12151,12153,12155,12157],{"class":237,"line":298},[235,12148,9740],{"class":1375},[235,12150,9743],{"class":519},[235,12152,4116],{"class":499},[235,12154,9748],{"class":252},[235,12156,2224],{"class":495},[235,12158,1348],{"class":499},[235,12160,12161,12163,12165,12167,12169,12171,12173],{"class":237,"line":380},[235,12162,9757],{"class":252},[235,12164,1705],{"class":495},[235,12166,9762],{"class":519},[235,12168,1694],{"class":499},[235,12170,9767],{"class":519},[235,12172,1715],{"class":495},[235,12174,1348],{"class":499},[235,12176,12177,12179,12181,12183,12185,12187,12189],{"class":237,"line":465},[235,12178,9776],{"class":252},[235,12180,1705],{"class":495},[235,12182,9762],{"class":519},[235,12184,1694],{"class":499},[235,12186,9785],{"class":519},[235,12188,1715],{"class":495},[235,12190,1348],{"class":499},[235,12192,12193],{"class":237,"line":590},[235,12194,1317],{"class":499},[13,12196,12197],{},"最後に上記の関数を連結し、イベントリスナーのコールバックに設定します。イベントリスナーはカードの追加ボタンに付与されています。",[81,12199,12200],{"id":12200},"実装後の動き",[13,12202,12203,12204,12207],{},"完成したデモは",[197,12205,7984],{"href":7982,"rel":12206},[201],"にあります。「ADD!」というボタンをクリックするとアニメーションつきでカードが追加されていきます。",[2399,12209,12210],{},"html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .s6YsC, html code.shiki .s6YsC{--shiki-default:#B2CCD6}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}",{"title":231,"searchDepth":259,"depth":259,"links":12212},[12213,12214,12218],{"id":7988,"depth":249,"text":7988},{"id":8669,"depth":249,"text":8670,"children":12215},[12216,12217],{"id":8673,"depth":259,"text":8674},{"id":8711,"depth":259,"text":8712},{"id":8728,"depth":249,"text":8728,"children":12219},[12220,12221,12222,12229],{"id":8731,"depth":259,"text":8731},{"id":9057,"depth":259,"text":9058},{"id":9341,"depth":259,"text":9341,"children":12223},[12224,12225,12226,12227,12228],{"id":10829,"depth":266,"text":10829},{"id":11122,"depth":266,"text":11122},{"id":11619,"depth":266,"text":11619},{"id":11672,"depth":266,"text":11672},{"id":12075,"depth":266,"text":12075},{"id":12200,"depth":259,"text":12200},[2427],"2021-07-14",{},"\u002Farticles\u002Fpinterest-like-style",{"title":7962,"description":7962},"articles\u002Fpinterest-like-style",[3947,8177,1262],"pinterest-like-style\u002Fthumbnail.png","Kk6is-f7e7A8CgIICoPK0ixaA9U5aJL-fp-oIvtU9PM",{"id":12240,"title":12241,"body":12242,"category":13450,"createdAt":13451,"description":13452,"extension":2430,"index":2439,"meta":13453,"navigation":262,"path":13454,"publish":262,"seo":13455,"series":2439,"seriesTitle":2439,"stem":13456,"tag":13457,"thumbnail":13459,"updatedAt":2439,"__hash__":13460},"articles\u002Farticles\u002Fstatic-site-search.md","AWS Cloud Searchを使用して静的コンテンツに検索機能をつける",{"type":10,"value":12243,"toc":13435},[12244,12247,12250,12253,12256,12259,12262,12279,12282,12285,12288,12297,12300,12303,12306,12309,12312,12315,12328,12331,12543,12549,12552,12560,12563,12566,12722,12729,12732,12735,12738,12741,12744,12748,12757,12760,12763,12771,12774,12781,12784,12791,12919,12922,12926,12929,13150,13160,13163,13166,13169,13172,13183,13186,13195,13199,13202,13205,13255,13258,13261,13264,13267,13270,13273,13276,13417,13420,13423,13426,13429,13432],[13,12245,12246],{},"こんにちはjunです。静的書き出しブログを作って数ヶ月後、ようやくこのブログにも「検索機能」を実装しました。静的ファイルの場合は検索といった動的な機能をつける際には工夫が必要です。",[13,12248,12249],{},"wordpressなどでは自身のプログラムとデータベースを用いて検索を行いますが、静的ブログではその２つがないので別途で準備する必要があります。つまり検索プログラムと検索対象のファイルをどこかに置き、さらにサイトからAjaxを用いてアクセスできるようにします。",[13,12251,12252],{},"私のサイトでは検索エンジンに「AWS Cloudsearch」というものを用いて実装しています。今回の記事でも同じようにCloudsearchを用いての解説を行います。",[74,12254,12255],{"id":12255},"全体の概要",[183,12257],{":src":12258,":width":3011},"'static-site-search\u002Fcloudsearch_build.jpg'",[13,12260,12261],{},"概要は上図のような感じです。検索機能自体はcloudsearchに任せ、cloudsearchを叩くAPI gatewayを通じてブラウザからアクセスします。これらの構成を実現するために以下の手順の実装が必要となります。",[10807,12263,12264,12267,12270,12273,12276],{},[20,12265,12266],{},"cloudsearchのインスタンス作成",[20,12268,12269],{},"検索対象のドキュメント（JSON）をcloudsearchにアップロード",[20,12271,12272],{},"API gateqwayからcloudsearchを叩くように連携",[20,12274,12275],{},"ウェブサイトから検索クエリを持たせたリクエストでAPIを叩く",[20,12277,12278],{},"結果をサイトに表示",[13,12280,12281],{},"それぞれの手順通りに説明していきます。",[74,12283,12284],{"id":12284},"cloudsearchのセットアップ",[81,12286,12287],{"id":12287},"cloudsearchのインスタンスを作成",[13,12289,12290,12291,12296],{},"AWSのアカウント作成などは省略します。AWSのメニューから",[197,12292,12295],{"href":12293,"rel":12294},"https:\u002F\u002Fap-northeast-1.console.aws.amazon.com\u002Fcloudsearch",[201],"cloudsearch","に移動します。リージョンを確認して、「Create a new search domain」をクリックして検索インスタンスを作成します。ここでいうドメインはURLのドメインという意味でなく、「Domain」は検索の区分みたいなものです。",[183,12298],{":src":12299,":width":3011},"'static-site-search\u002Fcloudsearch_start.png'",[13,12301,12302],{},"インスタンスの大きさなどを選択できますが、今回は一番小さいものにしておきます。Desired Instance Typeをsearch.small、Desired Replication Countを１にしました。",[81,12304,12305],{"id":12305},"インデックスフィールドの登録",[13,12307,12308],{},"次に検索対象のインデックスフィールドを登録します。",[183,12310],{":src":12311,":width":3011},"'static-site-search\u002Fset_document_key_config.png'",[13,12313,12314],{},"ここでいうインデックスフィールドとはタイトル、内容、カテゴリー、作成日時といった各ドキュメントの属性のことをいいます。インデックスフィールドを設定することでタイトルで検索、内容で検索、特定日時からの検索といった複雑な検索ができます。RDBでいうところのカラムみたいなものです。",[13,12316,12317,12318,12321,12322,12327],{},"もしドキュメントがある場合は",[39,12319,12320],{},"Analyze sample file(s) from my local machine","を選択しファイルをアップロードします。使用できるファイルは",[197,12323,12326],{"href":12324,"rel":12325},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fcloudsearch\u002Flatest\u002Fdeveloperguide\u002Fpreparing-data.html",[201],"XML,JSON,CSVがサポートされています。（詳細はこちら）","アップロードされたファイルから共通のインデックスフィールドを自動で設定してくれます。",[13,12329,12330],{},"私の場合は以下のようなcloudsearchの使用に従った構成でサンプルJSONを予め作成しておきました。",[226,12332,12336],{"className":12333,"code":12334,"language":12335,"meta":231,"style":231},"language-JSON shiki shiki-themes material-theme-ocean","[\n    {\n        \"type\":\"add\",\n        \"id\":\"bag-html-break-tag\",\n        \"fields\":{\n            \"description\":\"white-space： pre;で要素内で生じる、文章の隙間、インテンドの原因。\",\n            \"title\":\"white-space： pre;で要素内で生じる文章の隙間、インテンドの原因。\",\n            \"category\":[\"ministack\"],\n            \"tag\":[\"html\",\"css\",\"vue\"],\n            \"path\":\"https:\u002F\u002Fjun-app.com\u002Farticles\u002Fbag-html-break-tag\",\n            \"content\":\"~~~~~~~~~\"\n        }\n    }\n]\n","JSON",[39,12337,12338,12343,12347,12367,12386,12397,12418,12437,12459,12494,12513,12531,12535,12539],{"__ignoreMap":231},[235,12339,12340],{"class":237,"line":238},[235,12341,12342],{"class":499},"[\n",[235,12344,12345],{"class":237,"line":249},[235,12346,4030],{"class":499},[235,12348,12349,12352,12355,12357,12359,12361,12363,12365],{"class":237,"line":259},[235,12350,12351],{"class":499},"        \"",[235,12353,12354],{"class":1375},"type",[235,12356,1517],{"class":499},[235,12358,500],{"class":499},[235,12360,1517],{"class":499},[235,12362,10776],{"class":245},[235,12364,1517],{"class":499},[235,12366,1984],{"class":499},[235,12368,12369,12371,12373,12375,12377,12379,12382,12384],{"class":237,"line":266},[235,12370,12351],{"class":499},[235,12372,9785],{"class":1375},[235,12374,1517],{"class":499},[235,12376,500],{"class":499},[235,12378,1517],{"class":499},[235,12380,12381],{"class":245},"bag-html-break-tag",[235,12383,1517],{"class":499},[235,12385,1984],{"class":499},[235,12387,12388,12390,12393,12395],{"class":237,"line":275},[235,12389,12351],{"class":499},[235,12391,12392],{"class":1375},"fields",[235,12394,1517],{"class":499},[235,12396,5182],{"class":499},[235,12398,12399,12402,12405,12407,12409,12411,12414,12416],{"class":237,"line":283},[235,12400,12401],{"class":499},"            \"",[235,12403,12404],{"class":241},"description",[235,12406,1517],{"class":499},[235,12408,500],{"class":499},[235,12410,1517],{"class":499},[235,12412,12413],{"class":245},"white-space： pre;で要素内で生じる、文章の隙間、インテンドの原因。",[235,12415,1517],{"class":499},[235,12417,1984],{"class":499},[235,12419,12420,12422,12424,12426,12428,12430,12433,12435],{"class":237,"line":291},[235,12421,12401],{"class":499},[235,12423,9125],{"class":241},[235,12425,1517],{"class":499},[235,12427,500],{"class":499},[235,12429,1517],{"class":499},[235,12431,12432],{"class":245},"white-space： pre;で要素内で生じる文章の隙間、インテンドの原因。",[235,12434,1517],{"class":499},[235,12436,1984],{"class":499},[235,12438,12439,12441,12444,12446,12449,12451,12454,12456],{"class":237,"line":298},[235,12440,12401],{"class":499},[235,12442,12443],{"class":241},"category",[235,12445,1517],{"class":499},[235,12447,12448],{"class":499},":[",[235,12450,1517],{"class":499},[235,12452,12453],{"class":245},"ministack",[235,12455,1517],{"class":499},[235,12457,12458],{"class":499},"],\n",[235,12460,12461,12463,12466,12468,12470,12472,12474,12476,12478,12480,12482,12484,12486,12488,12490,12492],{"class":237,"line":380},[235,12462,12401],{"class":499},[235,12464,12465],{"class":241},"tag",[235,12467,1517],{"class":499},[235,12469,12448],{"class":499},[235,12471,1517],{"class":499},[235,12473,3947],{"class":245},[235,12475,1517],{"class":499},[235,12477,1404],{"class":499},[235,12479,1517],{"class":499},[235,12481,8177],{"class":245},[235,12483,1517],{"class":499},[235,12485,1404],{"class":499},[235,12487,1517],{"class":499},[235,12489,1208],{"class":245},[235,12491,1517],{"class":499},[235,12493,12458],{"class":499},[235,12495,12496,12498,12500,12502,12504,12506,12509,12511],{"class":237,"line":465},[235,12497,12401],{"class":499},[235,12499,2098],{"class":241},[235,12501,1517],{"class":499},[235,12503,500],{"class":499},[235,12505,1517],{"class":499},[235,12507,12508],{"class":245},"https:\u002F\u002Fjun-app.com\u002Farticles\u002Fbag-html-break-tag",[235,12510,1517],{"class":499},[235,12512,1984],{"class":499},[235,12514,12515,12517,12520,12522,12524,12526,12529],{"class":237,"line":590},[235,12516,12401],{"class":499},[235,12518,12519],{"class":241},"content",[235,12521,1517],{"class":499},[235,12523,500],{"class":499},[235,12525,1517],{"class":499},[235,12527,12528],{"class":245},"~~~~~~~~~",[235,12530,601],{"class":499},[235,12532,12533],{"class":237,"line":604},[235,12534,4086],{"class":499},[235,12536,12537],{"class":237,"line":612},[235,12538,2181],{"class":499},[235,12540,12541],{"class":237,"line":623},[235,12542,1444],{"class":499},[13,12544,12545,12546,12548],{},"この場合、",[39,12547,12392],{},"にある項目が自動に読みとれ、以下のように設定されます。",[183,12550],{":src":12551,":width":3011},"'static-site-search\u002Fconf_key.png'",[13,12553,12554,12555,12559],{},"インデックスフィールドの設定詳細は",[197,12556,7984],{"href":12557,"rel":12558},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fcloudsearch\u002Flatest\u002Fdeveloperguide\u002Fconfiguring-index-fields.html",[201],"を参考にしてください。",[81,12561,12562],{"id":12562},"アクセスポリシーの追加",[13,12564,12565],{},"次にこのcloudsearchインスタンスに対するアクセスポリシーを設定します。",[226,12567,12571],{"className":12568,"code":12569,"language":12570,"meta":231,"style":231},"language-json shiki shiki-themes material-theme-ocean","{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Principal\": {\n        \"AWS\": \"*\"\n      },\n      \"Action\": [\n        \"cloudsearch:search\",\n        \"cloudsearch:suggest\"\n      ]\n    }\n  ]\n}\n","json",[39,12572,12573,12577,12598,12611,12615,12636,12649,12666,12671,12684,12695,12704,12709,12713,12718],{"__ignoreMap":231},[235,12574,12575],{"class":237,"line":238},[235,12576,1976],{"class":499},[235,12578,12579,12582,12585,12587,12589,12591,12594,12596],{"class":237,"line":249},[235,12580,12581],{"class":499},"  \"",[235,12583,12584],{"class":1375},"Version",[235,12586,1517],{"class":499},[235,12588,500],{"class":499},[235,12590,595],{"class":499},[235,12592,12593],{"class":245},"2012-10-17",[235,12595,1517],{"class":499},[235,12597,1984],{"class":499},[235,12599,12600,12602,12605,12607,12609],{"class":237,"line":259},[235,12601,12581],{"class":499},[235,12603,12604],{"class":1375},"Statement",[235,12606,1517],{"class":499},[235,12608,500],{"class":499},[235,12610,1385],{"class":499},[235,12612,12613],{"class":237,"line":266},[235,12614,4030],{"class":499},[235,12616,12617,12620,12623,12625,12627,12629,12632,12634],{"class":237,"line":275},[235,12618,12619],{"class":499},"      \"",[235,12621,12622],{"class":241},"Effect",[235,12624,1517],{"class":499},[235,12626,500],{"class":499},[235,12628,595],{"class":499},[235,12630,12631],{"class":245},"Allow",[235,12633,1517],{"class":499},[235,12635,1984],{"class":499},[235,12637,12638,12640,12643,12645,12647],{"class":237,"line":283},[235,12639,12619],{"class":499},[235,12641,12642],{"class":241},"Principal",[235,12644,1517],{"class":499},[235,12646,500],{"class":499},[235,12648,1276],{"class":499},[235,12650,12651,12653,12656,12658,12660,12662,12664],{"class":237,"line":291},[235,12652,12351],{"class":499},[235,12654,12655],{"class":2836},"AWS",[235,12657,1517],{"class":499},[235,12659,500],{"class":499},[235,12661,595],{"class":499},[235,12663,8184],{"class":245},[235,12665,601],{"class":499},[235,12667,12668],{"class":237,"line":298},[235,12669,12670],{"class":499},"      },\n",[235,12672,12673,12675,12678,12680,12682],{"class":237,"line":380},[235,12674,12619],{"class":499},[235,12676,12677],{"class":241},"Action",[235,12679,1517],{"class":499},[235,12681,500],{"class":499},[235,12683,1385],{"class":499},[235,12685,12686,12688,12691,12693],{"class":237,"line":465},[235,12687,12351],{"class":499},[235,12689,12690],{"class":245},"cloudsearch:search",[235,12692,1517],{"class":499},[235,12694,1984],{"class":499},[235,12696,12697,12699,12702],{"class":237,"line":590},[235,12698,12351],{"class":499},[235,12700,12701],{"class":245},"cloudsearch:suggest",[235,12703,601],{"class":499},[235,12705,12706],{"class":237,"line":604},[235,12707,12708],{"class":499},"      ]\n",[235,12710,12711],{"class":237,"line":612},[235,12712,2181],{"class":499},[235,12714,12715],{"class":237,"line":623},[235,12716,12717],{"class":499},"  ]\n",[235,12719,12720],{"class":237,"line":634},[235,12721,1317],{"class":499},[13,12723,12724,12725,12728],{},"もう少し厳密にしたい人は ",[39,12726,12727],{},"\"AWS\": \"*\"","をロールベースにするなどします。これでAWSのサービス、すなわちAPI gatewayがこのcloudsearchの検索機能を使用できるようになりました。",[81,12730,12731],{"id":12731},"セットアップ完了",[13,12733,12734],{},"最後に確認をして適用します。設定の適用には10分ぐらい時間がかかるので気長に待ちます。この時は他の文書をアップロードするなどもできなくなります。",[183,12736],{":src":12737,":width":3011},"'static-site-search\u002Ffirst_setuop_complete.png'",[13,12739,12740],{},"このLOADINGという文字がACTIVEに変われば他の操作ができるようになります。",[183,12742],{":src":12743,":width":3011},"'static-site-search\u002Floading.png'",[74,12745,12747],{"id":12746},"api-gatewayの準備","API gatewayの準備",[13,12749,12750,12751,12756],{},"cloudsearchの処理が完了する間、API gatewayも実装しましょう。公式では",[197,12752,12755],{"href":12753,"rel":12754},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fcloudsearch\u002Flatest\u002Fdeveloperguide\u002Fapi-gateway.html",[201],"「Amazon CloudSearch と API Gateway の統合」"," こちらの記事が大変参考になります。",[13,12758,12759],{},"新しいAPIの作成まで行ったら、GETメソッドのAPIを選択します。そして「統合リクエスト」を選択します。ここでリクエストをAWSのサービスに連絡させます。",[183,12761],{":src":12762,":width":8692,":center":186},"'static-site-search\u002Fapi_setting.png'",[13,12764,12765,12766,12770],{},"上記の黒塗りにした箇所はcloudsearchのダッシュボードにある値を入れます。「AWSサブドメイン」は「Search Endpoint」、「実行ロール」はAPI gatewayがcloudsearchを叩くためのロールのARNを入れます。そのロールの作成は",[197,12767,7984],{"href":12768,"rel":12769},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fcloudsearch\u002Flatest\u002Fdeveloperguide\u002Fapi-gateway.html#api-gateway-pre",[201]," を確認してください。",[183,12772],{":src":12773,":width":8692,":center":186},"'static-site-search\u002Fdashboard.png'",[13,12775,12776,12777,12780],{},"最後に「URL クエリ文字列パラメータ」に「q」という名前でAPI gatewaryに含まれる ",[39,12778,12779],{},"method.request.querystring.q","をマッピングします。こうすることでクライアントからきたcloudsearchのクエリが、API gatewayを通じて実際のcloudsearchに渡されるようになりました。",[13,12782,12783],{},"次に「統合リクエスト」から一つ前の画面に戻って「メソッドリクエスト」の画面を開き、「リクエストの検証」の項目で「クエリ文字列パラメーターおよびヘッダーの検証」を選択します。そして先ほど設定したクエリパラメータ「q」を必須にするため、「URL クエリ文字列パラメータ」を開いて名前に「q」として必須にして確定します。こうすることで必ずリクエストにはcloudsearchで検索を行うためのクエリ文が含まれるようになりました。",[13,12785,12786,12787,12790],{},"テストを行い、クエリ文字列に",[39,12788,12789],{},"q=test","みたいに入れて送ってみましょう。ステータスが200で以下のようなレスポンスボディがあればcloudsearchが検索結果を返しています。",[226,12792,12794],{"className":12568,"code":12793,"language":12570,"meta":231,"style":231},"{\n  \"status\": {\n    \"rid\": \"~~~~~~\",\n    \"time-ms\": 1\n  },\n  \"hits\": {\n    \"found\": 0,\n    \"start\": 0,\n    \"hit\": []\n  }\n}\n",[39,12795,12796,12800,12813,12834,12848,12853,12866,12881,12896,12910,12915],{"__ignoreMap":231},[235,12797,12798],{"class":237,"line":238},[235,12799,1976],{"class":499},[235,12801,12802,12804,12807,12809,12811],{"class":237,"line":249},[235,12803,12581],{"class":499},[235,12805,12806],{"class":1375},"status",[235,12808,1517],{"class":499},[235,12810,500],{"class":499},[235,12812,1276],{"class":499},[235,12814,12815,12818,12821,12823,12825,12827,12830,12832],{"class":237,"line":259},[235,12816,12817],{"class":499},"    \"",[235,12819,12820],{"class":241},"rid",[235,12822,1517],{"class":499},[235,12824,500],{"class":499},[235,12826,595],{"class":499},[235,12828,12829],{"class":245},"~~~~~~",[235,12831,1517],{"class":499},[235,12833,1984],{"class":499},[235,12835,12836,12838,12841,12843,12845],{"class":237,"line":266},[235,12837,12817],{"class":499},[235,12839,12840],{"class":241},"time-ms",[235,12842,1517],{"class":499},[235,12844,500],{"class":499},[235,12846,12847],{"class":2836}," 1\n",[235,12849,12850],{"class":237,"line":275},[235,12851,12852],{"class":499},"  },\n",[235,12854,12855,12857,12860,12862,12864],{"class":237,"line":283},[235,12856,12581],{"class":499},[235,12858,12859],{"class":1375},"hits",[235,12861,1517],{"class":499},[235,12863,500],{"class":499},[235,12865,1276],{"class":499},[235,12867,12868,12870,12873,12875,12877,12879],{"class":237,"line":291},[235,12869,12817],{"class":499},[235,12871,12872],{"class":241},"found",[235,12874,1517],{"class":499},[235,12876,500],{"class":499},[235,12878,8197],{"class":2836},[235,12880,1984],{"class":499},[235,12882,12883,12885,12888,12890,12892,12894],{"class":237,"line":298},[235,12884,12817],{"class":499},[235,12886,12887],{"class":241},"start",[235,12889,1517],{"class":499},[235,12891,500],{"class":499},[235,12893,8197],{"class":2836},[235,12895,1984],{"class":499},[235,12897,12898,12900,12903,12905,12907],{"class":237,"line":380},[235,12899,12817],{"class":499},[235,12901,12902],{"class":241},"hit",[235,12904,1517],{"class":499},[235,12906,500],{"class":499},[235,12908,12909],{"class":499}," []\n",[235,12911,12912],{"class":237,"line":465},[235,12913,12914],{"class":499},"  }\n",[235,12916,12917],{"class":237,"line":590},[235,12918,1317],{"class":499},[13,12920,12921],{},"何も文書をアップロードしていなければhitしませんし、そしてCloudsearchがLOADINGだと返してくれないことがあります。テストが完了したらAPIをデプロイしてAPI gatewayの設定は完了です。あとはクライアントから適当に叩いてください。",[74,12923,12925],{"id":12924},"文書ページをアップロードする","文書（ページ）をアップロードする",[13,12927,12928],{},"それでは検索させる文書、静的ページの内容をアップロードしましょう。先述の通り以下のような形式のJSONにまとめます。",[226,12930,12932],{"className":12333,"code":12931,"language":12335,"meta":231,"style":231},"[\n    \u002F\u002F ここから\n    {\n        \"type\":\"add\",\n        \"id\":\"bag-html-break-tag\",\n        \"fields\":{\n            \"description\":\"white-space： pre;で要素内で生じる、文章の隙間、インテンドの原因。\",\n            \"title\":\"white-space： pre;で要素内で生じる文章の隙間、インテンドの原因。\",\n            \"category\":[\"ministack\"],\n            \"tag\":[\"html\",\"css\",\"vue\"],\n            \"path\":\"https:\u002F\u002Fjun-app.com\u002Farticles\u002Fbag-html-break-tag\",\n            \"content\":\"~~~~~~~~~\"\n        }\n    },\n    \u002F\u002F　これで１件の文書を追加するという意味。\n    {\n        ...\n    },\n    ...\n]\n",[39,12933,12934,12938,12943,12947,12965,12983,12993,13011,13029,13047,13081,13099,13115,13119,13123,13128,13132,13137,13141,13146],{"__ignoreMap":231},[235,12935,12936],{"class":237,"line":238},[235,12937,12342],{"class":499},[235,12939,12940],{"class":237,"line":249},[235,12941,12942],{"class":3119},"    \u002F\u002F ここから\n",[235,12944,12945],{"class":237,"line":259},[235,12946,4030],{"class":499},[235,12948,12949,12951,12953,12955,12957,12959,12961,12963],{"class":237,"line":266},[235,12950,12351],{"class":499},[235,12952,12354],{"class":1375},[235,12954,1517],{"class":499},[235,12956,500],{"class":499},[235,12958,1517],{"class":499},[235,12960,10776],{"class":245},[235,12962,1517],{"class":499},[235,12964,1984],{"class":499},[235,12966,12967,12969,12971,12973,12975,12977,12979,12981],{"class":237,"line":275},[235,12968,12351],{"class":499},[235,12970,9785],{"class":1375},[235,12972,1517],{"class":499},[235,12974,500],{"class":499},[235,12976,1517],{"class":499},[235,12978,12381],{"class":245},[235,12980,1517],{"class":499},[235,12982,1984],{"class":499},[235,12984,12985,12987,12989,12991],{"class":237,"line":283},[235,12986,12351],{"class":499},[235,12988,12392],{"class":1375},[235,12990,1517],{"class":499},[235,12992,5182],{"class":499},[235,12994,12995,12997,12999,13001,13003,13005,13007,13009],{"class":237,"line":291},[235,12996,12401],{"class":499},[235,12998,12404],{"class":241},[235,13000,1517],{"class":499},[235,13002,500],{"class":499},[235,13004,1517],{"class":499},[235,13006,12413],{"class":245},[235,13008,1517],{"class":499},[235,13010,1984],{"class":499},[235,13012,13013,13015,13017,13019,13021,13023,13025,13027],{"class":237,"line":298},[235,13014,12401],{"class":499},[235,13016,9125],{"class":241},[235,13018,1517],{"class":499},[235,13020,500],{"class":499},[235,13022,1517],{"class":499},[235,13024,12432],{"class":245},[235,13026,1517],{"class":499},[235,13028,1984],{"class":499},[235,13030,13031,13033,13035,13037,13039,13041,13043,13045],{"class":237,"line":380},[235,13032,12401],{"class":499},[235,13034,12443],{"class":241},[235,13036,1517],{"class":499},[235,13038,12448],{"class":499},[235,13040,1517],{"class":499},[235,13042,12453],{"class":245},[235,13044,1517],{"class":499},[235,13046,12458],{"class":499},[235,13048,13049,13051,13053,13055,13057,13059,13061,13063,13065,13067,13069,13071,13073,13075,13077,13079],{"class":237,"line":465},[235,13050,12401],{"class":499},[235,13052,12465],{"class":241},[235,13054,1517],{"class":499},[235,13056,12448],{"class":499},[235,13058,1517],{"class":499},[235,13060,3947],{"class":245},[235,13062,1517],{"class":499},[235,13064,1404],{"class":499},[235,13066,1517],{"class":499},[235,13068,8177],{"class":245},[235,13070,1517],{"class":499},[235,13072,1404],{"class":499},[235,13074,1517],{"class":499},[235,13076,1208],{"class":245},[235,13078,1517],{"class":499},[235,13080,12458],{"class":499},[235,13082,13083,13085,13087,13089,13091,13093,13095,13097],{"class":237,"line":590},[235,13084,12401],{"class":499},[235,13086,2098],{"class":241},[235,13088,1517],{"class":499},[235,13090,500],{"class":499},[235,13092,1517],{"class":499},[235,13094,12508],{"class":245},[235,13096,1517],{"class":499},[235,13098,1984],{"class":499},[235,13100,13101,13103,13105,13107,13109,13111,13113],{"class":237,"line":604},[235,13102,12401],{"class":499},[235,13104,12519],{"class":241},[235,13106,1517],{"class":499},[235,13108,500],{"class":499},[235,13110,1517],{"class":499},[235,13112,12528],{"class":245},[235,13114,601],{"class":499},[235,13116,13117],{"class":237,"line":612},[235,13118,4086],{"class":499},[235,13120,13121],{"class":237,"line":623},[235,13122,4091],{"class":499},[235,13124,13125],{"class":237,"line":634},[235,13126,13127],{"class":3119},"    \u002F\u002F　これで１件の文書を追加するという意味。\n",[235,13129,13130],{"class":237,"line":641},[235,13131,4030],{"class":499},[235,13133,13134],{"class":237,"line":653},[235,13135,13136],{"class":519},"        ...\n",[235,13138,13139],{"class":237,"line":661},[235,13140,4091],{"class":499},[235,13142,13143],{"class":237,"line":670},[235,13144,13145],{"class":519},"    ...\n",[235,13147,13148],{"class":237,"line":678},[235,13149,1444],{"class":499},[13,13151,13152,13153,1404,13155,1404,13157,13159],{},"ここでアップロードの際には上記のような",[39,13154,12354],{},[39,13156,9785],{},[39,13158,12392],{}," の3つのプロパティーを持つ必要があります。idは重複すると上書きされてしまうので、必ず異なるようにします。また後からわかるように何らかの規則があると、削除や上書きが簡単になります。私の場合は記事のマークダウンファイルの名前から取っています。私のブログはnuxt contentを使用しているのでnode.jsをいじってうんちゃらしています。頑張って文書分のjsonを用意してください。",[81,13161,13162],{"id":13162},"json化する際の注意点",[13,13164,13165],{},"文書のアップロードを行う時に失敗すると以下のような画面が表示されます。",[183,13167],{":src":13168,":width":3011,":center":186},"'static-site-search\u002Ffailed.png'",[13,13170,13171],{},"アップロードが失敗する原因と対策としてこの英文の通り",[10807,13173,13174,13177,13180],{},[20,13175,13176],{},"cloudsearchがACTIVEでなくLOADINGやNEED INDEX状態であるので、ACTIVEになるまで待つこと。（またはindex optionsでインデックスを走らせる）",[20,13178,13179],{},"single valueとして定義されたフィールドになっているのに、文書に複数の値が入っている。（自分もよくわからん）",[20,13181,13182],{},"cloudserachで定義されていないフィールドが文書にある。またはその逆。フィールドの設定をもう一度見直すか、文書のフィールドを設定し直す。",[13,13184,13185],{},"となります。",[13,13187,13188,13189,13194],{},"ただしフィールドなどを正しくしても何度も治らず、いろいろ検索しました。すると",[197,13190,13193],{"href":13191,"rel":13192},"https:\u002F\u002Fdocs.aws.amazon.com\u002Fja_jp\u002Fcloudsearch\u002Flatest\u002Fdeveloperguide\u002Fpreparing-data.html#:~:text=JSON%20%E3%83%90%E3%83%83%E3%83%81%E3%81%A8%20XML%20%E3%83%90%E3%83%83%E3%83%81%E3%81%AB%E3%81%AF%E3%81%A9%E3%81%A1%E3%82%89%E3%82%82%E3%80%81XML%20%E3%81%A7%E6%9C%89%E5%8A%B9%E3%81%AA%20UTF-8%20%E6%96%87%E5%AD%97%E3%81%AE%E3%81%BF%E3%82%92%E5%90%AB%E3%82%81%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82",[201],"公式ドキュメントのこの箇所","に解決策と思われる内容がありました。",[1225,13196,13198],{"className":13197},[1228,2914],"\nJSON バッチと XML バッチにはどちらも、XML で有効な UTF-8 文字のみを含めることができます。有効な文字は、制御文字のタブ（0009）、復帰（000D）、改行（000A）、および Unicode と ISO\u002FIEC 10646 での有効な文字です。FFFE、FFFF、サロゲートブロックの D800–DBFF と DC00–DFFF は無効で、エラーが発生します （詳細については、『Extensible Markup Language (XML) 1.0 (Fifth Edition)』 を参照してください)。無効な文字に一致する次の正規表現を使用して、無効な文字を削除することができます。\u002F[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]\u002F 。\n",[13,13200,13201],{},"つまり作成したJSONに無効なURF-8文字列が含まれており、エラーが起きていたのです。アップロードエラーには表示されないのでかなり詰まりました。",[13,13203,13204],{},"今回のjsonの場合、titleとcontentに対して上記の正規表現を使って無効な文字列を削除してます。node.jsの場合は以下の通りです。",[226,13206,13208],{"className":3990,"code":13207,"language":3992,"meta":231,"style":231},"data = data.replace(\n    \u002F[^\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]\u002Fg, \n    ''\n);\n",[39,13209,13210,13226,13244,13249],{"__ignoreMap":231},[235,13211,13212,13215,13217,13220,13222,13224],{"class":237,"line":238},[235,13213,13214],{"class":519},"data ",[235,13216,1382],{"class":499},[235,13218,13219],{"class":519}," data",[235,13221,1694],{"class":499},[235,13223,6315],{"class":252},[235,13225,4609],{"class":519},[235,13227,13228,13231,13234,13237,13240,13242],{"class":237,"line":249},[235,13229,13230],{"class":499},"    \u002F[^",[235,13232,13233],{"class":245},"\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD",[235,13235,13236],{"class":499},"]\u002F",[235,13238,13239],{"class":2836},"g",[235,13241,1404],{"class":499},[235,13243,520],{"class":519},[235,13245,13246],{"class":237,"line":259},[235,13247,13248],{"class":499},"    ''\n",[235,13250,13251,13253],{"class":237,"line":266},[235,13252,1715],{"class":519},[235,13254,1348],{"class":499},[13,13256,13257],{},"こうして直したjsonは無事、なんとかアップロードできました。どうやって見つけたかというと、１文書だけをいくつかのパターンに分けてアップロードすると、できるものとできないものがあって「使用される文字列が原因か？」となったのが決定打でした。",[81,13259,13260],{"id":13260},"テスト",[13,13262,13263],{},"Run a Test Searchにてクエリをテストして、文章がきちんと検索されているか、アップロードされているかをチェックしましょう。",[74,13265,13266],{"id":13266},"クライアント側の実装",[13,13268,13269],{},"これで検索機能の準備ができたので、API gatewayから必要なエンドポイントなどを取得してアクセスしてみましょう。",[183,13271],{":src":13272,":width":3011,":center":186},"'static-site-search\u002Fpage_sample.png'",[13,13274,13275],{},"ページ上ではこのようなUIとして、入力したキーワードで検索できるようにします。cloudsearchは複雑なクエリを組むこともできるのですが、今回は単純なものにします。",[226,13277,13279],{"className":3990,"code":13278,"language":3992,"meta":231,"style":231},"await fetch('https:\u002F\u002Fsample.sa-sample-1.amazonaws.com\u002Fv1?q='+this.query,{\n        method:'GET',\n        headers: {\n        'Content-Type': 'application\u002Fjson'\n        },\n    })\n.then(response => response.json())\n.then(jsondata => {\n    this.result = jsondata\n)\n",[39,13280,13281,13307,13323,13332,13350,13354,13361,13385,13400,13413],{"__ignoreMap":231},[235,13282,13283,13286,13289,13291,13293,13296,13298,13301,13304],{"class":237,"line":238},[235,13284,13285],{"class":1269},"await",[235,13287,13288],{"class":252}," fetch",[235,13290,1705],{"class":519},[235,13292,1345],{"class":499},[235,13294,13295],{"class":245},"https:\u002F\u002Fsample.sa-sample-1.amazonaws.com\u002Fv1?q=",[235,13297,1345],{"class":499},[235,13299,13300],{"class":499},"+this.",[235,13302,13303],{"class":519},"query",[235,13305,13306],{"class":499},",{\n",[235,13308,13309,13312,13314,13316,13319,13321],{"class":237,"line":249},[235,13310,13311],{"class":495},"        method",[235,13313,500],{"class":499},[235,13315,1345],{"class":499},[235,13317,13318],{"class":245},"GET",[235,13320,1345],{"class":499},[235,13322,1984],{"class":499},[235,13324,13325,13328,13330],{"class":237,"line":259},[235,13326,13327],{"class":495},"        headers",[235,13329,500],{"class":499},[235,13331,1276],{"class":499},[235,13333,13334,13336,13339,13341,13343,13345,13348],{"class":237,"line":266},[235,13335,2145],{"class":499},[235,13337,13338],{"class":495},"Content-Type",[235,13340,1345],{"class":499},[235,13342,500],{"class":499},[235,13344,503],{"class":499},[235,13346,13347],{"class":245},"application\u002Fjson",[235,13349,509],{"class":499},[235,13351,13352],{"class":237,"line":275},[235,13353,5276],{"class":499},[235,13355,13356,13359],{"class":237,"line":283},[235,13357,13358],{"class":499},"    }",[235,13360,1953],{"class":519},[235,13362,13363,13365,13368,13370,13373,13375,13378,13380,13382],{"class":237,"line":291},[235,13364,1694],{"class":499},[235,13366,13367],{"class":252},"then",[235,13369,1705],{"class":519},[235,13371,13372],{"class":4527},"response",[235,13374,4533],{"class":1375},[235,13376,13377],{"class":519}," response",[235,13379,1694],{"class":499},[235,13381,12570],{"class":252},[235,13383,13384],{"class":519},"())\n",[235,13386,13387,13389,13391,13393,13396,13398],{"class":237,"line":298},[235,13388,1694],{"class":499},[235,13390,13367],{"class":252},[235,13392,1705],{"class":519},[235,13394,13395],{"class":4527},"jsondata",[235,13397,4533],{"class":1375},[235,13399,1276],{"class":499},[235,13401,13402,13405,13408,13410],{"class":237,"line":380},[235,13403,13404],{"class":499},"    this.",[235,13406,13407],{"class":519},"result",[235,13409,4116],{"class":499},[235,13411,13412],{"class":519}," jsondata\n",[235,13414,13415],{"class":237,"line":465},[235,13416,1953],{"class":495},[13,13418,13419],{},"方法は単純でバリデーションを行った後に、API gatewayのエンドポイントにクエリ付きでアクセスします。",[183,13421],{":src":13422,":width":3011,":center":186},"'static-site-search\u002Fresult.png'",[13,13424,13425],{},"ページのURLなどもフィールドを含まれており、レスポンスで返すようにしています。それを用いてこのように一覧のリンクを作れば検索機能は実装完了です。",[13,13427,13428],{},"今回は検索エンジンにAWS cloudsearchを使用しましたが、他にも文書検索サービスはたくさんあります。商用で利用する場合は検索文書を自動的にアップロードしたりする機能や、より複雑なクエリの構築、キャッシュの利用が必要となります。",[13,13430,13431],{},"以上が静的ページに検索機能を持たせる方法です。最後見てくださりありがとうございました。",[2399,13433,13434],{},"html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}",{"title":231,"searchDepth":259,"depth":259,"links":13436},[13437,13438,13444,13445,13449],{"id":12255,"depth":249,"text":12255},{"id":12284,"depth":249,"text":12284,"children":13439},[13440,13441,13442,13443],{"id":12287,"depth":259,"text":12287},{"id":12305,"depth":259,"text":12305},{"id":12562,"depth":259,"text":12562},{"id":12731,"depth":259,"text":12731},{"id":12746,"depth":249,"text":12747},{"id":12924,"depth":249,"text":12925,"children":13446},[13447,13448],{"id":13162,"depth":259,"text":13162},{"id":13260,"depth":259,"text":13260},{"id":13266,"depth":249,"text":13266},[2427],"2021-06-28","Google Search以外にも方法があります！AWS Cloud Searchを使って静的サイトに検索機能をつける。",{},"\u002Farticles\u002Fstatic-site-search",{"title":12241,"description":13452},"articles\u002Fstatic-site-search",[13458,1262],"aws","static-site-search\u002Fthumbnail.png","CvPv7DEIqq4ZRH1_F9I9qcalQq9c5xGj_OltNaXdZ3k",{"id":13462,"title":3891,"body":13463,"category":16960,"createdAt":16961,"description":16962,"extension":2430,"index":249,"meta":16963,"navigation":262,"path":16964,"publish":262,"seo":16965,"series":7953,"seriesTitle":7954,"stem":16966,"tag":16967,"thumbnail":7958,"updatedAt":2439,"__hash__":16968},"series\u002Fseries\u002Fwell-study-webpack-2.md",{"type":10,"value":13464,"toc":16939},[13465,13469,13475,13485,13488,13491,13494,13505,13511,13520,13552,13562,13623,13629,13824,13834,13837,13851,13861,13864,13867,13870,13876,13882,14456,14459,14462,14465,14603,14606,14613,14626,14629,14697,14706,14725,14731,14737,14743,14759,14762,14771,14808,14811,14823,14826,14829,14839,15330,15343,15346,15348,15351,15354,15357,15363,15366,15548,15551,15569,15573,15576,15582,15595,15879,15882,15888,15891,15894,15905,15999,16013,16470,16494,16496,16499,16507,16514,16517,16532,16538,16547,16551,16564,16723,16728,16799,16809,16909,16931,16933,16936],[1225,13466,13468],{"className":13467},[1228,2914],"\n2021年10月30日：修正事項があっため追記しました。\n",[13,13470,3887,13471,13474],{},[197,13472,13473],{"href":3916},"ちゃんと理解するWebpack5。１：webpack基礎とSass・jsのバンドル","の続きの記事です。前回はjsファイルのバンドル、scssのコンパイルを行いました。今回はそこから",[17,13476,13477,13479,13482],{},[20,13478,5040],{},[20,13480,13481],{},"babelを用いたトランスコンパイル",[20,13483,13484],{},"複数のバンドルファイルを出力",[13,13486,13487],{},"以上を解説したいと思います。これらができればひとまず意図通りのwebコンテンツが作れるようになります。コードは前回のものから発展させて使用します。それではまず画像パスの解決から行っていきます。",[74,13489,13490],{"id":13490},"webpackで画像を取り扱う",[81,13492,13493],{"id":13493},"画像が必要なシチュエーションを準備",[13,13495,13496,13497,13500,13501,13504],{},"sassでは背景画像などで画像のパスが必要となることがあります。",[39,13498,13499],{},"\u002Fsrc","に",[39,13502,13503],{},"imgs","ディレクトリを作成します。",[226,13506,13509],{"className":13507,"code":13508,"language":934},[932],".\n├── dist\n│   ├── bundle.js\n│   ├── index.html\n│   └── style.css\n├── package-lock.json\n├── package.json\n├── src\n│   ├── imgs    \u002F\u002F new!\n│   ├── js\n│   │   ├── functions.js\n│   │   └── main.js\n│   └── sass\n│       ├── compnent.scss\n│       ├── style.scss\n│       └── variable.scss\n├── node_modules\n└── webpack.config.js\n",[39,13510,13508],{"__ignoreMap":231},[13,13512,13513,13515,13516,13519],{},[39,13514,5066],{},"ディレクトリにに画像を配置していきます。適当な画像sample.jpgをおいておき、sassにも適当な",[39,13517,13518],{},"background-image","を設定します。",[226,13521,13526],{"className":13522,"code":13523,"filename":13524,"language":13525,"meta":231,"style":231},"language-sass shiki shiki-themes material-theme-ocean",".image-box{\n    width: 100px;\n    height: 100px;\n    background-image: url('~\u002Fimgs\u002Fsample.jpg');\n}\n","\u002Fsrc\u002Fsass\u002Fcomponent.scss","sass",[39,13527,13528,13533,13538,13543,13548],{"__ignoreMap":231},[235,13529,13530],{"class":237,"line":238},[235,13531,13532],{},".image-box{\n",[235,13534,13535],{"class":237,"line":249},[235,13536,13537],{},"    width: 100px;\n",[235,13539,13540],{"class":237,"line":259},[235,13541,13542],{},"    height: 100px;\n",[235,13544,13545],{"class":237,"line":266},[235,13546,13547],{},"    background-image: url('~\u002Fimgs\u002Fsample.jpg');\n",[235,13549,13550],{"class":237,"line":275},[235,13551,1317],{},[13,13553,13554,13557,13558,13561],{},[39,13555,13556],{},"url('..\u002Fimgs\u002Fsample.jpg');","のような相対パスでなく",[39,13559,13560],{},"url('~\u002Fimgs\u002Fsample.jpg');","としたのは運用上のテクニックです。後でこの説明をしますので、ひとまずこんなパスにしておきます。まだ設定していませんが、試しにビルドしてみます。",[226,13563,13566],{"className":8175,"code":13564,"filename":13565,"language":8177,"meta":231,"style":231},".image-box {\n  width: 100px;\n  height: 100px;\n  background-image: url(\"~\u002Fimgs\u002Fsample.jpg\"); }\n","dist\u002Fstyle.css",[39,13567,13568,13577,13589,13600],{"__ignoreMap":231},[235,13569,13570,13572,13575],{"class":237,"line":238},[235,13571,1694],{"class":499},[235,13573,13574],{"class":241},"image-box",[235,13576,1276],{"class":499},[235,13578,13579,13582,13584,13587],{"class":237,"line":249},[235,13580,13581],{"class":8191},"  width",[235,13583,500],{"class":499},[235,13585,13586],{"class":2836}," 100px",[235,13588,1348],{"class":499},[235,13590,13591,13594,13596,13598],{"class":237,"line":259},[235,13592,13593],{"class":8191},"  height",[235,13595,500],{"class":499},[235,13597,13586],{"class":2836},[235,13599,1348],{"class":499},[235,13601,13602,13605,13607,13609,13611,13613,13616,13618,13621],{"class":237,"line":266},[235,13603,13604],{"class":8191},"  background-image",[235,13606,500],{"class":499},[235,13608,6816],{"class":252},[235,13610,1705],{"class":499},[235,13612,1517],{"class":499},[235,13614,13615],{"class":245},"~\u002Fimgs\u002Fsample.jpg",[235,13617,1517],{"class":499},[235,13619,13620],{"class":499},");",[235,13622,6823],{"class":499},[13,13624,13625,13628],{},[39,13626,13627],{},"component.scss","で定義した通りのURLとなりましたが、もちろん不正なので404となります。",[226,13630,13633],{"className":5051,"code":13631,"filename":13632,"language":3947,"meta":231,"style":231},"    ...\n    \u003Cbody>\n        \u003Cmain>\n            \u003Cdiv id='app'>\n\n            \u003C\u002Fdiv>\n            \u003Cinput type=\"text\" value=\"\" id=\"inputs\">\n            \u003Cbutton id=\"submmit\" >追加する\u003C\u002Fbutton>\n            \u003Cdiv class='box'>\u003C\u002Fdiv>\n            \u003Cdiv class='image-box'>\u003C\u002Fdiv>\n        \u003C\u002Fmain>\n    \u003C\u002Fbody>\n    ...\n    \u003C!-- Failed to load resource: net::ERR_FILE_NOT_FOUND \u002F~\u002Fimgs\u002Fsample.jpg-->\n","\u002Fdist\u002Findex.html",[39,13634,13635,13639,13647,13656,13675,13679,13687,13725,13754,13777,13799,13807,13815,13819],{"__ignoreMap":231},[235,13636,13637],{"class":237,"line":238},[235,13638,13145],{"class":519},[235,13640,13641,13643,13645],{"class":237,"line":249},[235,13642,1492],{"class":499},[235,13644,4677],{"class":495},[235,13646,1487],{"class":499},[235,13648,13649,13651,13654],{"class":237,"line":259},[235,13650,1506],{"class":499},[235,13652,13653],{"class":495},"main",[235,13655,1487],{"class":499},[235,13657,13658,13660,13662,13664,13666,13668,13671,13673],{"class":237,"line":266},[235,13659,9208],{"class":499},[235,13661,1225],{"class":495},[235,13663,8017],{"class":1375},[235,13665,1382],{"class":499},[235,13667,1345],{"class":499},[235,13669,13670],{"class":245},"app",[235,13672,1345],{"class":499},[235,13674,1487],{"class":499},[235,13676,13677],{"class":237,"line":275},[235,13678,263],{"emptyLinePlaceholder":262},[235,13680,13681,13683,13685],{"class":237,"line":283},[235,13682,9241],{"class":499},[235,13684,1225],{"class":495},[235,13686,1487],{"class":499},[235,13688,13689,13691,13694,13696,13698,13700,13702,13704,13707,13709,13712,13714,13716,13718,13721,13723],{"class":237,"line":291},[235,13690,9208],{"class":499},[235,13692,13693],{"class":495},"input",[235,13695,9310],{"class":1375},[235,13697,1382],{"class":499},[235,13699,1517],{"class":499},[235,13701,934],{"class":245},[235,13703,1517],{"class":499},[235,13705,13706],{"class":1375}," value",[235,13708,1382],{"class":499},[235,13710,13711],{"class":499},"\"\"",[235,13713,8017],{"class":1375},[235,13715,1382],{"class":499},[235,13717,1517],{"class":499},[235,13719,13720],{"class":245},"inputs",[235,13722,1517],{"class":499},[235,13724,1487],{"class":499},[235,13726,13727,13729,13731,13733,13735,13737,13740,13742,13745,13748,13750,13752],{"class":237,"line":298},[235,13728,9208],{"class":499},[235,13730,9252],{"class":495},[235,13732,8017],{"class":1375},[235,13734,1382],{"class":499},[235,13736,1517],{"class":499},[235,13738,13739],{"class":245},"submmit",[235,13741,1517],{"class":499},[235,13743,13744],{"class":499}," >",[235,13746,13747],{"class":519},"追加する",[235,13749,1530],{"class":499},[235,13751,9252],{"class":495},[235,13753,1487],{"class":499},[235,13755,13756,13758,13760,13762,13764,13766,13769,13771,13773,13775],{"class":237,"line":380},[235,13757,9208],{"class":499},[235,13759,1225],{"class":495},[235,13761,8005],{"class":1375},[235,13763,1382],{"class":499},[235,13765,1345],{"class":499},[235,13767,13768],{"class":245},"box",[235,13770,1345],{"class":499},[235,13772,8809],{"class":499},[235,13774,1225],{"class":495},[235,13776,1487],{"class":499},[235,13778,13779,13781,13783,13785,13787,13789,13791,13793,13795,13797],{"class":237,"line":465},[235,13780,9208],{"class":499},[235,13782,1225],{"class":495},[235,13784,8005],{"class":1375},[235,13786,1382],{"class":499},[235,13788,1345],{"class":499},[235,13790,13574],{"class":245},[235,13792,1345],{"class":499},[235,13794,8809],{"class":499},[235,13796,1225],{"class":495},[235,13798,1487],{"class":499},[235,13800,13801,13803,13805],{"class":237,"line":590},[235,13802,9278],{"class":499},[235,13804,13653],{"class":495},[235,13806,1487],{"class":499},[235,13808,13809,13811,13813],{"class":237,"line":604},[235,13810,1539],{"class":499},[235,13812,4677],{"class":495},[235,13814,1487],{"class":499},[235,13816,13817],{"class":237,"line":612},[235,13818,13145],{"class":519},[235,13820,13821],{"class":237,"line":623},[235,13822,13823],{"class":3119},"    \u003C!-- Failed to load resource: net::ERR_FILE_NOT_FOUND \u002F~\u002Fimgs\u002Fsample.jpg-->\n",[13,13825,13826,13827,13830,13831,13833],{},"相対リンクでやってもdist配下ににimgsディレクトリと画像そのものがないので、404となります。そのためwebpackを用いて",[39,13828,13829],{},"\u002Fsrc\u002Fimgs","と配下の画像をdistに移動し、",[39,13832,13560],{},"のようなパスを変換させてあげる必要があります。",[81,13835,13836],{"id":13836},"webpack4と5の違い",[13,13838,13839,13840,13843,13844,13843,13847,13850],{},"webpack4では画像の処理に",[39,13841,13842],{},"url-loader","、",[39,13845,13846],{},"raw-loader",[39,13848,13849],{},"file-loader","を使用していましたが、webpack5ではすでにwebpackに搭載されているAsset Modulesで行います。ただバージョン4の書き方もまだ主流なので、今回は4と5の方法を紹介し、最終的には5の方法で実装しようと思います。",[13,13852,13853,13854,13856,13857,13860],{},"なお、目指す形としては",[39,13855,7549],{},"配下に",[39,13858,13859],{},"\u002Fimgs","というディレクトリが作られ、そこに配下の画像が移動され、sassの画像パスが正しくなっているように設定します。",[81,13862,13863],{"id":13863},"webpack4の設定でやってみる",[88,13865,13866],{"id":13866},"loaderをインストールとconfigの記述を変更",[13,13868,13869],{},"それでは従来の方法での説明をまずは行います。最初に必要なloaderをインストールします。",[226,13871,13874],{"className":13872,"code":13873,"language":934},[932],"npm i -D url-loader file-loader\n",[39,13875,13873],{"__ignoreMap":231},[13,13877,13878,13879,13881],{},"この2つを用いてパスの解決とファイルの移動を行うことができます。そして",[39,13880,2046],{},"を以下のように変更します。",[226,13883,13885],{"className":3990,"code":13884,"filename":2046,"language":3992,"meta":231,"style":231},"const MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst path = require('path'); \u002F\u002F 追加\nmodule.exports = {\n    \u002F\u002Fバンドル対象のファイル\n    entry: .\u002Fsrc\u002Fjs\u002Fmain.js',\n  \n    mode:\"development\",\n    \n    module: {\n        rules: [\n            {\n                test: \u002F\\.(sa|sc|c)ss$\u002F,\n                exclude: \u002Fnode_modules\u002F,\n                use: [\n                    MiniCssExtractPlugin.loader,\n                    {\n                        loader: 'css-loader',\n                        options: { url: true }　\u002F\u002F trueに変更\n                    },\n                    'sass-loader',\n                ]\n            },\n            {   \u002F\u002F追加\n                test: \u002F\\.(png|jpg|gif)$\u002Fi,\n                use: [\n                  {\n                    loader: 'url-loader',\n                    options: {\n                      limit: 8192,\n                      name:'.\u002Fimgs\u002F[name].[ext]'\n                    }\n                  },\n                ],\n               type: 'javascript\u002Fauto' \u002F\u002F 大切\n            },\n        ],\n    },\n    resolve:{　\u002F\u002F追加\n        alias: {\n          '~': path.resolve(__dirname, 'src')\n        }\n    },\n    \u002F\u002F ファイルの出力設定\n    output: {\n        \u002F\u002F  出力ファイルのディレクトリ名\n        path: `${__dirname}\u002Fdist`,\n        \u002F\u002F 出力ファイル名\n        filename: \"bundle.js\"\n    },\n    plugins: [\n        new MiniCssExtractPlugin({\n            filename: 'style.css'\n        })\n    ]\n};\n",[39,13886,13887,13909,13935,13943,13948,13975,13979,13992,13996,14004,14012,14016,14049,14064,14073,14084,14089,14104,14125,14130,14141,14146,14150,14158,14190,14198,14203,14218,14227,14239,14253,14258,14263,14270,14287,14291,14297,14301,14311,14319,14347,14351,14355,14359,14367,14371,14389,14394,14407,14411,14419,14429,14442,14448,14452],{"__ignoreMap":231},[235,13888,13889,13891,13893,13895,13897,13899,13901,13903,13905,13907],{"class":237,"line":238},[235,13890,1376],{"class":1375},[235,13892,4254],{"class":519},[235,13894,1382],{"class":499},[235,13896,1702],{"class":252},[235,13898,1705],{"class":519},[235,13900,1345],{"class":499},[235,13902,4265],{"class":245},[235,13904,1345],{"class":499},[235,13906,1715],{"class":519},[235,13908,1348],{"class":499},[235,13910,13911,13913,13915,13917,13919,13921,13923,13925,13927,13929,13932],{"class":237,"line":249},[235,13912,1376],{"class":1375},[235,13914,2087],{"class":519},[235,13916,1382],{"class":499},[235,13918,1702],{"class":252},[235,13920,1705],{"class":519},[235,13922,1345],{"class":499},[235,13924,2098],{"class":245},[235,13926,1345],{"class":499},[235,13928,1715],{"class":519},[235,13930,13931],{"class":499},";",[235,13933,13934],{"class":3119}," \u002F\u002F 追加\n",[235,13936,13937,13939,13941],{"class":237,"line":259},[235,13938,4220],{"class":499},[235,13940,4116],{"class":499},[235,13942,1276],{"class":499},[235,13944,13945],{"class":237,"line":266},[235,13946,13947],{"class":3119},"    \u002F\u002Fバンドル対象のファイル\n",[235,13949,13950,13952,13954,13957,13959,13961,13963,13965,13967,13969,13971,13973],{"class":237,"line":275},[235,13951,4123],{"class":495},[235,13953,500],{"class":499},[235,13955,13956],{"class":499}," .\u002F",[235,13958,3925],{"class":519},[235,13960,4055],{"class":499},[235,13962,1262],{"class":519},[235,13964,4055],{"class":499},[235,13966,13653],{"class":519},[235,13968,1694],{"class":499},[235,13970,1262],{"class":519},[235,13972,1345],{"class":499},[235,13974,1984],{"class":245},[235,13976,13977],{"class":237,"line":283},[235,13978,4139],{"class":519},[235,13980,13981,13984,13986,13988,13990],{"class":237,"line":291},[235,13982,13983],{"class":519},"    mode:",[235,13985,1517],{"class":499},[235,13987,4151],{"class":245},[235,13989,1517],{"class":499},[235,13991,1984],{"class":499},[235,13993,13994],{"class":237,"line":298},[235,13995,4160],{"class":519},[235,13997,13998,14000,14002],{"class":237,"line":380},[235,13999,4165],{"class":495},[235,14001,500],{"class":499},[235,14003,1276],{"class":499},[235,14005,14006,14008,14010],{"class":237,"line":465},[235,14007,4174],{"class":495},[235,14009,500],{"class":499},[235,14011,1385],{"class":519},[235,14013,14014],{"class":237,"line":590},[235,14015,6787],{"class":499},[235,14017,14018,14021,14023,14025,14027,14029,14031,14033,14035,14037,14039,14041,14043,14045,14047],{"class":237,"line":604},[235,14019,14020],{"class":495},"                test",[235,14022,500],{"class":499},[235,14024,4040],{"class":499},[235,14026,4043],{"class":519},[235,14028,1705],{"class":499},[235,14030,6726],{"class":245},[235,14032,6729],{"class":499},[235,14034,6732],{"class":245},[235,14036,6729],{"class":499},[235,14038,6737],{"class":245},[235,14040,1715],{"class":499},[235,14042,6742],{"class":245},[235,14044,4052],{"class":1269},[235,14046,4055],{"class":499},[235,14048,1984],{"class":499},[235,14050,14051,14054,14056,14058,14060,14062],{"class":237,"line":612},[235,14052,14053],{"class":495},"                exclude",[235,14055,500],{"class":499},[235,14057,4040],{"class":499},[235,14059,5754],{"class":245},[235,14061,4055],{"class":499},[235,14063,1984],{"class":499},[235,14065,14066,14069,14071],{"class":237,"line":623},[235,14067,14068],{"class":495},"                use",[235,14070,500],{"class":499},[235,14072,1385],{"class":519},[235,14074,14075,14078,14080,14082],{"class":237,"line":634},[235,14076,14077],{"class":519},"                    MiniCssExtractPlugin",[235,14079,1694],{"class":499},[235,14081,6780],{"class":519},[235,14083,1984],{"class":499},[235,14085,14086],{"class":237,"line":641},[235,14087,14088],{"class":499},"                    {\n",[235,14090,14091,14094,14096,14098,14100,14102],{"class":237,"line":653},[235,14092,14093],{"class":495},"                        loader",[235,14095,500],{"class":499},[235,14097,503],{"class":499},[235,14099,6799],{"class":245},[235,14101,1345],{"class":499},[235,14103,1984],{"class":499},[235,14105,14106,14109,14111,14113,14115,14117,14119,14122],{"class":237,"line":661},[235,14107,14108],{"class":495},"                        options",[235,14110,500],{"class":499},[235,14112,6813],{"class":499},[235,14114,6816],{"class":495},[235,14116,500],{"class":499},[235,14118,5805],{"class":4702},[235,14120,14121],{"class":499}," }",[235,14123,14124],{"class":3119},"　\u002F\u002F trueに変更\n",[235,14126,14127],{"class":237,"line":670},[235,14128,14129],{"class":499},"                    },\n",[235,14131,14132,14135,14137,14139],{"class":237,"line":678},[235,14133,14134],{"class":499},"                    '",[235,14136,6835],{"class":245},[235,14138,1345],{"class":499},[235,14140,1984],{"class":499},[235,14142,14143],{"class":237,"line":686},[235,14144,14145],{"class":519},"                ]\n",[235,14147,14148],{"class":237,"line":694},[235,14149,6828],{"class":499},[235,14151,14152,14155],{"class":237,"line":702},[235,14153,14154],{"class":499},"            {",[235,14156,14157],{"class":3119},"   \u002F\u002F追加\n",[235,14159,14160,14162,14164,14166,14168,14170,14172,14174,14176,14178,14180,14182,14184,14186,14188],{"class":237,"line":712},[235,14161,14020],{"class":495},[235,14163,500],{"class":499},[235,14165,4040],{"class":499},[235,14167,4043],{"class":519},[235,14169,1705],{"class":499},[235,14171,6869],{"class":245},[235,14173,6729],{"class":499},[235,14175,6874],{"class":245},[235,14177,6729],{"class":499},[235,14179,6879],{"class":245},[235,14181,1715],{"class":499},[235,14183,4052],{"class":1269},[235,14185,4055],{"class":499},[235,14187,6893],{"class":2836},[235,14189,1984],{"class":499},[235,14191,14192,14194,14196],{"class":237,"line":723},[235,14193,14068],{"class":495},[235,14195,500],{"class":499},[235,14197,1385],{"class":519},[235,14199,14200],{"class":237,"line":730},[235,14201,14202],{"class":499},"                  {\n",[235,14204,14205,14208,14210,14212,14214,14216],{"class":237,"line":741},[235,14206,14207],{"class":495},"                    loader",[235,14209,500],{"class":499},[235,14211,503],{"class":499},[235,14213,13842],{"class":245},[235,14215,1345],{"class":499},[235,14217,1984],{"class":499},[235,14219,14220,14223,14225],{"class":237,"line":752},[235,14221,14222],{"class":495},"                    options",[235,14224,500],{"class":499},[235,14226,1276],{"class":499},[235,14228,14229,14232,14234,14237],{"class":237,"line":763},[235,14230,14231],{"class":495},"                      limit",[235,14233,500],{"class":499},[235,14235,14236],{"class":2836}," 8192",[235,14238,1984],{"class":499},[235,14240,14241,14244,14246,14248,14251],{"class":237,"line":774},[235,14242,14243],{"class":495},"                      name",[235,14245,500],{"class":499},[235,14247,1345],{"class":499},[235,14249,14250],{"class":245},".\u002Fimgs\u002F[name].[ext]",[235,14252,509],{"class":499},[235,14254,14255],{"class":237,"line":785},[235,14256,14257],{"class":499},"                    }\n",[235,14259,14260],{"class":237,"line":794},[235,14261,14262],{"class":499},"                  },\n",[235,14264,14265,14268],{"class":237,"line":806},[235,14266,14267],{"class":519},"                ]",[235,14269,1984],{"class":499},[235,14271,14272,14275,14277,14279,14282,14284],{"class":237,"line":815},[235,14273,14274],{"class":495},"               type",[235,14276,500],{"class":499},[235,14278,503],{"class":499},[235,14280,14281],{"class":245},"javascript\u002Fauto",[235,14283,1345],{"class":499},[235,14285,14286],{"class":3119}," \u002F\u002F 大切\n",[235,14288,14289],{"class":237,"line":823},[235,14290,6828],{"class":499},[235,14292,14293,14295],{"class":237,"line":833},[235,14294,6844],{"class":519},[235,14296,1984],{"class":499},[235,14298,14299],{"class":237,"line":3537},[235,14300,4091],{"class":499},[235,14302,14303,14305,14308],{"class":237,"line":3542},[235,14304,2127],{"class":495},[235,14306,14307],{"class":499},":{",[235,14309,14310],{"class":3119},"　\u002F\u002F追加\n",[235,14312,14313,14315,14317],{"class":237,"line":3547},[235,14314,5235],{"class":495},[235,14316,500],{"class":499},[235,14318,1276],{"class":499},[235,14320,14321,14323,14325,14327,14329,14331,14333,14335,14337,14339,14341,14343,14345],{"class":237,"line":3553},[235,14322,7446],{"class":499},[235,14324,5247],{"class":495},[235,14326,1345],{"class":499},[235,14328,500],{"class":499},[235,14330,1393],{"class":519},[235,14332,1694],{"class":499},[235,14334,2158],{"class":252},[235,14336,4640],{"class":519},[235,14338,1404],{"class":499},[235,14340,503],{"class":499},[235,14342,3925],{"class":245},[235,14344,1345],{"class":499},[235,14346,1953],{"class":519},[235,14348,14349],{"class":237,"line":3558},[235,14350,4086],{"class":499},[235,14352,14353],{"class":237,"line":3564},[235,14354,4091],{"class":499},[235,14356,14357],{"class":237,"line":4},[235,14358,7515],{"class":3119},[235,14360,14361,14363,14365],{"class":237,"line":3575},[235,14362,7521],{"class":495},[235,14364,500],{"class":499},[235,14366,1276],{"class":499},[235,14368,14369],{"class":237,"line":3581},[235,14370,7531],{"class":3119},[235,14372,14373,14375,14377,14379,14381,14383,14385,14387],{"class":237,"line":3587},[235,14374,7537],{"class":495},[235,14376,500],{"class":499},[235,14378,4631],{"class":499},[235,14380,7544],{"class":519},[235,14382,1950],{"class":499},[235,14384,7549],{"class":245},[235,14386,7552],{"class":499},[235,14388,1984],{"class":499},[235,14390,14391],{"class":237,"line":3593},[235,14392,14393],{"class":3119},"        \u002F\u002F 出力ファイル名\n",[235,14395,14396,14398,14400,14402,14405],{"class":237,"line":3599},[235,14397,4626],{"class":495},[235,14399,500],{"class":499},[235,14401,595],{"class":499},[235,14403,14404],{"class":245},"bundle.js",[235,14406,601],{"class":499},[235,14408,14409],{"class":237,"line":3605},[235,14410,4091],{"class":499},[235,14412,14413,14415,14417],{"class":237,"line":3611},[235,14414,7580],{"class":495},[235,14416,500],{"class":499},[235,14418,1385],{"class":519},[235,14420,14421,14423,14425,14427],{"class":237,"line":3616},[235,14422,7590],{"class":499},[235,14424,7593],{"class":252},[235,14426,1705],{"class":519},[235,14428,1976],{"class":499},[235,14430,14431,14433,14435,14437,14440],{"class":237,"line":3621},[235,14432,6909],{"class":495},[235,14434,500],{"class":499},[235,14436,503],{"class":499},[235,14438,14439],{"class":245},"style.css",[235,14441,509],{"class":499},[235,14443,14444,14446],{"class":237,"line":3626},[235,14445,7617],{"class":499},[235,14447,1953],{"class":519},[235,14449,14450],{"class":237,"line":3632},[235,14451,7627],{"class":519},[235,14453,14454],{"class":237,"line":7238},[235,14455,7633],{"class":499},[13,14457,14458],{},"それでは細かい説明をします。",[88,14460,14461],{"id":14461},"file-loaderの設定",[13,14463,14464],{},"file-loaderではjpg,png,gifの拡張子を見つけた時の処理を記述します。",[226,14466,14468],{"className":3990,"code":14467,"filename":2046,"language":3992,"meta":231,"style":231},"{\n    test: \u002F\\.(png|jpg|gif)$\u002Fi,\n    use: [\n        {\n        loader: 'url-loader',\n        options: {\n            limit: 8192,\n            name:'.\u002Fimgs\u002F[name].[ext]'\n        }\n        },\n    ],\n    type: 'javascript\u002Fauto' \u002F\u002F大切\n},\n",[39,14469,14470,14474,14507,14516,14520,14535,14544,14555,14568,14572,14576,14583,14599],{"__ignoreMap":231},[235,14471,14472],{"class":237,"line":238},[235,14473,1976],{"class":499},[235,14475,14476,14479,14481,14483,14485,14487,14489,14491,14493,14495,14497,14499,14501,14503,14505],{"class":237,"line":249},[235,14477,14478],{"class":241},"    test",[235,14480,500],{"class":499},[235,14482,4040],{"class":499},[235,14484,4043],{"class":519},[235,14486,1705],{"class":499},[235,14488,6869],{"class":245},[235,14490,6729],{"class":499},[235,14492,6874],{"class":245},[235,14494,6729],{"class":499},[235,14496,6879],{"class":245},[235,14498,1715],{"class":499},[235,14500,4052],{"class":1269},[235,14502,4055],{"class":499},[235,14504,6893],{"class":2836},[235,14506,1984],{"class":499},[235,14508,14509,14512,14514],{"class":237,"line":259},[235,14510,14511],{"class":241},"    use",[235,14513,500],{"class":499},[235,14515,1385],{"class":495},[235,14517,14518],{"class":237,"line":266},[235,14519,7136],{"class":499},[235,14521,14522,14525,14527,14529,14531,14533],{"class":237,"line":275},[235,14523,14524],{"class":495},"        loader",[235,14526,500],{"class":499},[235,14528,503],{"class":499},[235,14530,13842],{"class":245},[235,14532,1345],{"class":499},[235,14534,1984],{"class":499},[235,14536,14537,14540,14542],{"class":237,"line":283},[235,14538,14539],{"class":495},"        options",[235,14541,500],{"class":499},[235,14543,1276],{"class":499},[235,14545,14546,14549,14551,14553],{"class":237,"line":291},[235,14547,14548],{"class":495},"            limit",[235,14550,500],{"class":499},[235,14552,14236],{"class":2836},[235,14554,1984],{"class":499},[235,14556,14557,14560,14562,14564,14566],{"class":237,"line":298},[235,14558,14559],{"class":495},"            name",[235,14561,500],{"class":499},[235,14563,1345],{"class":499},[235,14565,14250],{"class":245},[235,14567,509],{"class":499},[235,14569,14570],{"class":237,"line":380},[235,14571,4086],{"class":499},[235,14573,14574],{"class":237,"line":465},[235,14575,5276],{"class":499},[235,14577,14578,14581],{"class":237,"line":590},[235,14579,14580],{"class":495},"    ]",[235,14582,1984],{"class":499},[235,14584,14585,14588,14590,14592,14594,14596],{"class":237,"line":604},[235,14586,14587],{"class":241},"    type",[235,14589,500],{"class":499},[235,14591,503],{"class":499},[235,14593,14281],{"class":245},[235,14595,1345],{"class":499},[235,14597,14598],{"class":3119}," \u002F\u002F大切\n",[235,14600,14601],{"class":237,"line":612},[235,14602,1414],{"class":499},[13,14604,14605],{},"loaderにはurl-loaderを指定してファイルをURIに変換できるようにします。",[13,14607,14608,14609,14612],{},"distでは画像はimgsディレクトリ配下に格納させますので、",[39,14610,14611],{},"name:'.\u002Fimgs\u002F[name].[ext]'","としておきます。sass,jsの画像ファイルの参照もこのディレクトリ構成にあったパスに変更してくれます。",[13,14614,14615,14616,14619,14620,14625],{},"webpack5で従来の方法を使う場合、",[39,14617,14618],{},"type: 'javascript\u002Fauto'","を忘れないようにしてください。",[197,14621,14624],{"href":14622,"rel":14623},"https:\u002F\u002Fwebpack.js.org\u002Fguides\u002Fasset-modules\u002F",[201],"公式ドキュメントの記述はこちら。"," webpack5にはAsset Moduleというものがすでにあり、それがfile-loader達と似たような働きを行います。もし先ほどの記述がないと二重で処理が入るなどがしておかしくなります。",[88,14627,14628],{"id":14628},"エイリアスの設定",[226,14630,14632],{"className":3990,"code":14631,"filename":2046,"language":3992,"meta":231,"style":231},"{\n    resolve:{　\u002F\u002F追加\n        alias: {\n          '~': path.resolve(__dirname, 'src')\n        }\n    },\n},\n",[39,14633,14634,14638,14646,14654,14685,14689,14693],{"__ignoreMap":231},[235,14635,14636],{"class":237,"line":238},[235,14637,1976],{"class":499},[235,14639,14640,14642,14644],{"class":237,"line":249},[235,14641,2127],{"class":241},[235,14643,14307],{"class":499},[235,14645,14310],{"class":3119},[235,14647,14648,14650,14652],{"class":237,"line":259},[235,14649,5235],{"class":241},[235,14651,500],{"class":499},[235,14653,1276],{"class":499},[235,14655,14656,14658,14660,14662,14665,14667,14669,14671,14673,14675,14677,14679,14681,14683],{"class":237,"line":266},[235,14657,7446],{"class":499},[235,14659,5247],{"class":245},[235,14661,1345],{"class":499},[235,14663,14664],{"class":495},": ",[235,14666,2098],{"class":519},[235,14668,1694],{"class":499},[235,14670,2158],{"class":252},[235,14672,1705],{"class":495},[235,14674,7544],{"class":519},[235,14676,1404],{"class":499},[235,14678,503],{"class":499},[235,14680,3925],{"class":245},[235,14682,1345],{"class":499},[235,14684,1953],{"class":495},[235,14686,14687],{"class":237,"line":275},[235,14688,4086],{"class":499},[235,14690,14691],{"class":237,"line":283},[235,14692,4091],{"class":499},[235,14694,14695],{"class":237,"line":291},[235,14696,1414],{"class":499},[13,14698,14699,14701,14702,14705],{},[39,14700,2158],{},"ではwebpackがデフォルトで持っている、名前解決に新しい設定を追加したり、変更することができます。ここでは先ほど",[39,14703,14704],{},"~\u002Fimg\u002Ftest.png","みたいな書き方をしたパスを正しいパスに変換する処理を書いています。",[13,14707,14708,14710,14711,14714,14715,14717,14718,14721,14722,14724],{},[39,14709,5247],{},"はエイリアスとして設定しました。",[39,14712,14713],{},"'~': path.resolve(__dirname, 'src')","とすることで、",[39,14716,5247],{},"を見つけたら",[39,14719,14720],{},"path.resolve(__dirname, 'src')","というに変換するんだなとwebpackが読み取ります。ちなみに",[39,14723,14720],{},"というのはこのファイル（今回のwebpack.config.js）が置かれているOS上のパスのことです。macのあるディレクトリで構築していると以下の様に変換されます。",[226,14726,14729],{"className":14727,"code":14728,"language":934},[932],"\u002FUsers\u002Fjun\u002FDesktop\u002Fmy_apps\u002Fwebpack_practice\u002Fsrc\n",[39,14730,14728],{"__ignoreMap":231},[13,14732,14733,14734,14736],{},"もう少しざっくり説明するとこの",[39,14735,3925],{},"ディレクトリを指しています。",[226,14738,14741],{"className":14739,"code":14740,"language":934},[932],".\n├── dist\n│   ├── bundle.js\n│   ├── index.html\n│   └── style.css\n├── package-lock.json\n├── package.json\n├── src　           \u002F\u002F←ここ！！ = path.resolve(__dirname, 'src')\n│   ├── imgs \n│   ├── js\n│   │   ├── functions.js\n│   │   └── main.js\n│   └── sass\n│       ├── compnent.scss\n│       ├── style.scss\n│       └── variable.scss\n├── node_modules\n└── webpack.config.js\n",[39,14742,14740],{"__ignoreMap":231},[13,14744,14745,14746,14749,14750,14752,14753,14755,14756,14758],{},"つまり、sassで",[39,14747,14748],{},"~\u002Fimgs\u002Ftest.png","とすれば",[39,14751,5247],{},"を自動に変換して",[39,14754,3925],{},"配下の",[39,14757,13503],{},"の画像にバインドされます。このように特定ディレクトリやそのパスを別名で呼ぶことをエイリアス（alias）といいます。",[13,14760,14761],{},"ではなぜエイリアスで呼ぶことがいいのでしょうか？それは階層が深くなるほど、相対パスの指定では苦労するからです。他にも相対パスで指定すると、imgsディレクトリの位置を変えたいとなった時に全ての相対パスを変更する必要があります。srcディレクトリをエイリアスにすることで、相対パスでしていなくても良くなります。画像を使いたい場合は",[226,14763,14765],{"className":13522,"code":14764,"language":13525,"meta":231,"style":231},"background-image('~\u002Fimgs\u002Ftest.png')\n",[39,14766,14767],{"__ignoreMap":231},[235,14768,14769],{"class":237,"line":238},[235,14770,14764],{},[226,14772,14774],{"className":3990,"code":14773,"language":3992,"meta":231,"style":231},"import img from '~\u002Fimgs\u002Ftest.png';\nconsole.log(img);\n",[39,14775,14776,14793],{"__ignoreMap":231},[235,14777,14778,14780,14783,14785,14787,14789,14791],{"class":237,"line":238},[235,14779,1331],{"class":1269},[235,14781,14782],{"class":519}," img ",[235,14784,1337],{"class":1269},[235,14786,503],{"class":499},[235,14788,14748],{"class":245},[235,14790,1345],{"class":499},[235,14792,1348],{"class":499},[235,14794,14795,14798,14800,14803,14806],{"class":237,"line":249},[235,14796,14797],{"class":519},"console",[235,14799,1694],{"class":499},[235,14801,14802],{"class":252},"log",[235,14804,14805],{"class":519},"(img)",[235,14807,1348],{"class":499},[13,14809,14810],{},"と指定すればよくなります。ディレクトリ構成の変更にも柔軟に対応できます。",[1225,14812,14815,14816,14818,14819,14822],{"className":14813},[1228,14814],"alert-success","\nエイリアスは干渉しなければいろいろ設定できます。今回は",[39,14817,3925],{},"直下ですが、",[39,14820,14821],{},"src\u002Fimgs","を指す画像用エイリアスなんかも作成できます。プロジェクトに合わせて設定しましょう。\n",[13,14824,14825],{},"これで画像ファイルが利用できる様になります。次はwebpack5の方法でやってみましょう。",[81,14827,14828],{"id":14828},"webpack5でのやり方",[13,14830,14831,14832,1404,14834,1404,14836,14838],{},"webpack5の方法では結構簡単になりました。webpack4でインストールした",[39,14833,13846],{},[39,14835,13842],{},[39,14837,13849],{},"は必要ありません。",[226,14840,14842],{"className":3990,"code":14841,"filename":2046,"language":3992,"meta":231,"style":231},"const MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst path = require('path');\nmodule.exports = {\n    \u002F\u002Fバンドル対象のファイル\n    entry: .\u002Fsrc\u002Fjs\u002Fmain.js',\n  \n    mode:\"development\",\n    \n    module: {\n        rules: [\n            {\n                test: \u002F\\.(sa|sc|c)ss$\u002F,\n                exclude: \u002Fnode_modules\u002F,\n                use: [\n                    MiniCssExtractPlugin.loader,\n                    {\n                        loader: 'css-loader',\n                        options: { url: true }\n                    },\n                    'sass-loader',\n                ]\n            },\n            {\n                test: \u002F\\.(png|jpg|gif)$\u002Fi,\n                \u002F\u002F ここから変更。useがなくなり。typeが変更されている。\n                generator: {\n                    filename: 'imgs\u002F[name][ext][query]'\n                },\n                type: 'asset\u002Fresource'\n            },\n        ],\n    },\n    resolve:{\n        alias: {\n          '~': path.resolve(__dirname, 'src')\n        }\n    },\n    \u002F\u002F ファイルの出力設定\n    output: {\n        \u002F\u002F  出力ファイルのディレクトリ名\n        path: `${__dirname}\u002Fdist`,\n        \u002F\u002F 出力ファイル名\n        filename: \"bundle.js\"\n    },\n    plugins: [\n        new MiniCssExtractPlugin({\n            filename: 'style.css'\n        })\n    ]\n};\n",[39,14843,14844,14866,14888,14896,14900,14926,14930,14942,14946,14954,14962,14966,14998,15012,15020,15030,15034,15048,15064,15068,15078,15082,15086,15090,15122,15127,15136,15150,15155,15168,15172,15178,15182,15188,15196,15224,15228,15232,15236,15244,15248,15266,15270,15282,15286,15294,15304,15316,15322,15326],{"__ignoreMap":231},[235,14845,14846,14848,14850,14852,14854,14856,14858,14860,14862,14864],{"class":237,"line":238},[235,14847,1376],{"class":1375},[235,14849,4254],{"class":519},[235,14851,1382],{"class":499},[235,14853,1702],{"class":252},[235,14855,1705],{"class":519},[235,14857,1345],{"class":499},[235,14859,4265],{"class":245},[235,14861,1345],{"class":499},[235,14863,1715],{"class":519},[235,14865,1348],{"class":499},[235,14867,14868,14870,14872,14874,14876,14878,14880,14882,14884,14886],{"class":237,"line":249},[235,14869,1376],{"class":1375},[235,14871,2087],{"class":519},[235,14873,1382],{"class":499},[235,14875,1702],{"class":252},[235,14877,1705],{"class":519},[235,14879,1345],{"class":499},[235,14881,2098],{"class":245},[235,14883,1345],{"class":499},[235,14885,1715],{"class":519},[235,14887,1348],{"class":499},[235,14889,14890,14892,14894],{"class":237,"line":259},[235,14891,4220],{"class":499},[235,14893,4116],{"class":499},[235,14895,1276],{"class":499},[235,14897,14898],{"class":237,"line":266},[235,14899,13947],{"class":3119},[235,14901,14902,14904,14906,14908,14910,14912,14914,14916,14918,14920,14922,14924],{"class":237,"line":275},[235,14903,4123],{"class":495},[235,14905,500],{"class":499},[235,14907,13956],{"class":499},[235,14909,3925],{"class":519},[235,14911,4055],{"class":499},[235,14913,1262],{"class":519},[235,14915,4055],{"class":499},[235,14917,13653],{"class":519},[235,14919,1694],{"class":499},[235,14921,1262],{"class":519},[235,14923,1345],{"class":499},[235,14925,1984],{"class":245},[235,14927,14928],{"class":237,"line":283},[235,14929,4139],{"class":519},[235,14931,14932,14934,14936,14938,14940],{"class":237,"line":291},[235,14933,13983],{"class":519},[235,14935,1517],{"class":499},[235,14937,4151],{"class":245},[235,14939,1517],{"class":499},[235,14941,1984],{"class":499},[235,14943,14944],{"class":237,"line":298},[235,14945,4160],{"class":519},[235,14947,14948,14950,14952],{"class":237,"line":380},[235,14949,4165],{"class":495},[235,14951,500],{"class":499},[235,14953,1276],{"class":499},[235,14955,14956,14958,14960],{"class":237,"line":465},[235,14957,4174],{"class":495},[235,14959,500],{"class":499},[235,14961,1385],{"class":519},[235,14963,14964],{"class":237,"line":590},[235,14965,6787],{"class":499},[235,14967,14968,14970,14972,14974,14976,14978,14980,14982,14984,14986,14988,14990,14992,14994,14996],{"class":237,"line":604},[235,14969,14020],{"class":495},[235,14971,500],{"class":499},[235,14973,4040],{"class":499},[235,14975,4043],{"class":519},[235,14977,1705],{"class":499},[235,14979,6726],{"class":245},[235,14981,6729],{"class":499},[235,14983,6732],{"class":245},[235,14985,6729],{"class":499},[235,14987,6737],{"class":245},[235,14989,1715],{"class":499},[235,14991,6742],{"class":245},[235,14993,4052],{"class":1269},[235,14995,4055],{"class":499},[235,14997,1984],{"class":499},[235,14999,15000,15002,15004,15006,15008,15010],{"class":237,"line":612},[235,15001,14053],{"class":495},[235,15003,500],{"class":499},[235,15005,4040],{"class":499},[235,15007,5754],{"class":245},[235,15009,4055],{"class":499},[235,15011,1984],{"class":499},[235,15013,15014,15016,15018],{"class":237,"line":623},[235,15015,14068],{"class":495},[235,15017,500],{"class":499},[235,15019,1385],{"class":519},[235,15021,15022,15024,15026,15028],{"class":237,"line":634},[235,15023,14077],{"class":519},[235,15025,1694],{"class":499},[235,15027,6780],{"class":519},[235,15029,1984],{"class":499},[235,15031,15032],{"class":237,"line":641},[235,15033,14088],{"class":499},[235,15035,15036,15038,15040,15042,15044,15046],{"class":237,"line":653},[235,15037,14093],{"class":495},[235,15039,500],{"class":499},[235,15041,503],{"class":499},[235,15043,6799],{"class":245},[235,15045,1345],{"class":499},[235,15047,1984],{"class":499},[235,15049,15050,15052,15054,15056,15058,15060,15062],{"class":237,"line":661},[235,15051,14108],{"class":495},[235,15053,500],{"class":499},[235,15055,6813],{"class":499},[235,15057,6816],{"class":495},[235,15059,500],{"class":499},[235,15061,5805],{"class":4702},[235,15063,6823],{"class":499},[235,15065,15066],{"class":237,"line":670},[235,15067,14129],{"class":499},[235,15069,15070,15072,15074,15076],{"class":237,"line":678},[235,15071,14134],{"class":499},[235,15073,6835],{"class":245},[235,15075,1345],{"class":499},[235,15077,1984],{"class":499},[235,15079,15080],{"class":237,"line":686},[235,15081,14145],{"class":519},[235,15083,15084],{"class":237,"line":694},[235,15085,6828],{"class":499},[235,15087,15088],{"class":237,"line":702},[235,15089,6787],{"class":499},[235,15091,15092,15094,15096,15098,15100,15102,15104,15106,15108,15110,15112,15114,15116,15118,15120],{"class":237,"line":712},[235,15093,14020],{"class":495},[235,15095,500],{"class":499},[235,15097,4040],{"class":499},[235,15099,4043],{"class":519},[235,15101,1705],{"class":499},[235,15103,6869],{"class":245},[235,15105,6729],{"class":499},[235,15107,6874],{"class":245},[235,15109,6729],{"class":499},[235,15111,6879],{"class":245},[235,15113,1715],{"class":499},[235,15115,4052],{"class":1269},[235,15117,4055],{"class":499},[235,15119,6893],{"class":2836},[235,15121,1984],{"class":499},[235,15123,15124],{"class":237,"line":723},[235,15125,15126],{"class":3119},"                \u002F\u002F ここから変更。useがなくなり。typeが変更されている。\n",[235,15128,15129,15132,15134],{"class":237,"line":730},[235,15130,15131],{"class":495},"                generator",[235,15133,500],{"class":499},[235,15135,1276],{"class":499},[235,15137,15138,15141,15143,15145,15148],{"class":237,"line":741},[235,15139,15140],{"class":495},"                    filename",[235,15142,500],{"class":499},[235,15144,503],{"class":499},[235,15146,15147],{"class":245},"imgs\u002F[name][ext][query]",[235,15149,509],{"class":499},[235,15151,15152],{"class":237,"line":752},[235,15153,15154],{"class":499},"                },\n",[235,15156,15157,15160,15162,15164,15166],{"class":237,"line":763},[235,15158,15159],{"class":495},"                type",[235,15161,500],{"class":499},[235,15163,503],{"class":499},[235,15165,6934],{"class":245},[235,15167,509],{"class":499},[235,15169,15170],{"class":237,"line":774},[235,15171,6828],{"class":499},[235,15173,15174,15176],{"class":237,"line":785},[235,15175,6844],{"class":519},[235,15177,1984],{"class":499},[235,15179,15180],{"class":237,"line":794},[235,15181,4091],{"class":499},[235,15183,15184,15186],{"class":237,"line":806},[235,15185,2127],{"class":495},[235,15187,5182],{"class":499},[235,15189,15190,15192,15194],{"class":237,"line":815},[235,15191,5235],{"class":495},[235,15193,500],{"class":499},[235,15195,1276],{"class":499},[235,15197,15198,15200,15202,15204,15206,15208,15210,15212,15214,15216,15218,15220,15222],{"class":237,"line":823},[235,15199,7446],{"class":499},[235,15201,5247],{"class":495},[235,15203,1345],{"class":499},[235,15205,500],{"class":499},[235,15207,1393],{"class":519},[235,15209,1694],{"class":499},[235,15211,2158],{"class":252},[235,15213,4640],{"class":519},[235,15215,1404],{"class":499},[235,15217,503],{"class":499},[235,15219,3925],{"class":245},[235,15221,1345],{"class":499},[235,15223,1953],{"class":519},[235,15225,15226],{"class":237,"line":833},[235,15227,4086],{"class":499},[235,15229,15230],{"class":237,"line":3537},[235,15231,4091],{"class":499},[235,15233,15234],{"class":237,"line":3542},[235,15235,7515],{"class":3119},[235,15237,15238,15240,15242],{"class":237,"line":3547},[235,15239,7521],{"class":495},[235,15241,500],{"class":499},[235,15243,1276],{"class":499},[235,15245,15246],{"class":237,"line":3553},[235,15247,7531],{"class":3119},[235,15249,15250,15252,15254,15256,15258,15260,15262,15264],{"class":237,"line":3558},[235,15251,7537],{"class":495},[235,15253,500],{"class":499},[235,15255,4631],{"class":499},[235,15257,7544],{"class":519},[235,15259,1950],{"class":499},[235,15261,7549],{"class":245},[235,15263,7552],{"class":499},[235,15265,1984],{"class":499},[235,15267,15268],{"class":237,"line":3564},[235,15269,14393],{"class":3119},[235,15271,15272,15274,15276,15278,15280],{"class":237,"line":4},[235,15273,4626],{"class":495},[235,15275,500],{"class":499},[235,15277,595],{"class":499},[235,15279,14404],{"class":245},[235,15281,601],{"class":499},[235,15283,15284],{"class":237,"line":3575},[235,15285,4091],{"class":499},[235,15287,15288,15290,15292],{"class":237,"line":3581},[235,15289,7580],{"class":495},[235,15291,500],{"class":499},[235,15293,1385],{"class":519},[235,15295,15296,15298,15300,15302],{"class":237,"line":3587},[235,15297,7590],{"class":499},[235,15299,7593],{"class":252},[235,15301,1705],{"class":519},[235,15303,1976],{"class":499},[235,15305,15306,15308,15310,15312,15314],{"class":237,"line":3593},[235,15307,6909],{"class":495},[235,15309,500],{"class":499},[235,15311,503],{"class":499},[235,15313,14439],{"class":245},[235,15315,509],{"class":499},[235,15317,15318,15320],{"class":237,"line":3599},[235,15319,7617],{"class":499},[235,15321,1953],{"class":519},[235,15323,15324],{"class":237,"line":3605},[235,15325,7627],{"class":519},[235,15327,15328],{"class":237,"line":3611},[235,15329,7633],{"class":499},[13,15331,15332,15333,15335,15336,15338,15339,15342],{},"変わった箇所はpng,jpg,gifの",[39,15334,3986],{},"の設定です。4の設定ではloaderを使用するために",[39,15337,1832],{},"で設定しました。しかし5では",[39,15340,15341],{},"type: 'asset\u002Fresource'","を使用すること4で実装していた動きを実装できます。",[13,15344,15345],{},"エイリアスなどの設定は変わりません。webpackにおける画像ファイルの設定以上となります。",[74,15347,13481],{"id":13481},[13,15349,15350],{},"これらの設定があればひとまずsassとjsを用いた作成ができそうです。ですがwebエンジニアを悩ませるこれの対策をしなくてはいけません。",[183,15352],{":src":15353,":width":8692,":center":186},"'_mix\u002FInternet-Explorer-Logo.png'",[13,15355,15356],{},"Interner Explorer（以後IE）です。特にJSが影響を受けます。JSにはES5、ES6という2種類の記述方法があります。今回はその違いの説明は省きますが、ES6はES5より効率的な書き方ができます。しかしIEはES5の書き方しか受け付けず、ES6の書き方は構文エラーを起こして実行できないというクソ仕様です。",[13,15358,15359,15360,15362],{},"そのためES6のJSを使用するにはES5の記述に変換する必要があります。その変換をしてくれるのがBabelです。webpackには",[39,15361,7204],{},"というものがあるので、それを利用してバンドルと同時に変換（トランスコンパイル）を行いましょう。",[13,15364,15365],{},"試しにIEでは使用できないアロー関数と定数宣言を書いておきます。",[226,15367,15370],{"className":3990,"code":15368,"filename":15369,"language":3992,"meta":231,"style":231},"import $ from 'jquery';\nimport funcs from '.\u002Ffunctions';\nimport '~\u002Fsass\u002Fstyle.scss';\n\n$('#submmit').on('click',()=>{\n    return funcs.addNewText('#app','#inputs');\n})\n\nconst message = \"use in IE\";\n()=>{\n    console.log(message)\n}\n","main.js",[39,15371,15372,15390,15408,15421,15425,15459,15492,15498,15502,15520,15528,15544],{"__ignoreMap":231},[235,15373,15374,15376,15379,15381,15383,15386,15388],{"class":237,"line":238},[235,15375,1331],{"class":1269},[235,15377,15378],{"class":519}," $ ",[235,15380,1337],{"class":1269},[235,15382,503],{"class":499},[235,15384,15385],{"class":245},"jquery",[235,15387,1345],{"class":499},[235,15389,1348],{"class":499},[235,15391,15392,15394,15397,15399,15401,15404,15406],{"class":237,"line":249},[235,15393,1331],{"class":1269},[235,15395,15396],{"class":519}," funcs ",[235,15398,1337],{"class":1269},[235,15400,503],{"class":499},[235,15402,15403],{"class":245},".\u002Ffunctions",[235,15405,1345],{"class":499},[235,15407,1348],{"class":499},[235,15409,15410,15412,15414,15417,15419],{"class":237,"line":259},[235,15411,1331],{"class":1269},[235,15413,503],{"class":499},[235,15415,15416],{"class":245},"~\u002Fsass\u002Fstyle.scss",[235,15418,1345],{"class":499},[235,15420,1348],{"class":499},[235,15422,15423],{"class":237,"line":266},[235,15424,263],{"emptyLinePlaceholder":262},[235,15426,15427,15429,15431,15433,15436,15438,15440,15442,15445,15447,15449,15451,15453,15455,15457],{"class":237,"line":275},[235,15428,4052],{"class":252},[235,15430,1705],{"class":519},[235,15432,1345],{"class":499},[235,15434,15435],{"class":245},"#submmit",[235,15437,1345],{"class":499},[235,15439,1715],{"class":519},[235,15441,1694],{"class":499},[235,15443,15444],{"class":252},"on",[235,15446,1705],{"class":519},[235,15448,1345],{"class":499},[235,15450,9682],{"class":245},[235,15452,1345],{"class":499},[235,15454,9687],{"class":499},[235,15456,9690],{"class":1375},[235,15458,1976],{"class":499},[235,15460,15461,15463,15466,15468,15471,15473,15475,15477,15479,15481,15483,15486,15488,15490],{"class":237,"line":283},[235,15462,9697],{"class":1269},[235,15464,15465],{"class":519}," funcs",[235,15467,1694],{"class":499},[235,15469,15470],{"class":252},"addNewText",[235,15472,1705],{"class":495},[235,15474,1345],{"class":499},[235,15476,2009],{"class":245},[235,15478,1345],{"class":499},[235,15480,1404],{"class":499},[235,15482,1345],{"class":499},[235,15484,15485],{"class":245},"#inputs",[235,15487,1345],{"class":499},[235,15489,1715],{"class":495},[235,15491,1348],{"class":499},[235,15493,15494,15496],{"class":237,"line":291},[235,15495,1950],{"class":499},[235,15497,1953],{"class":519},[235,15499,15500],{"class":237,"line":298},[235,15501,263],{"emptyLinePlaceholder":262},[235,15503,15504,15506,15509,15511,15513,15516,15518],{"class":237,"line":380},[235,15505,1376],{"class":1375},[235,15507,15508],{"class":519}," message ",[235,15510,1382],{"class":499},[235,15512,595],{"class":499},[235,15514,15515],{"class":245},"use in IE",[235,15517,1517],{"class":499},[235,15519,1348],{"class":499},[235,15521,15522,15524,15526],{"class":237,"line":465},[235,15523,2224],{"class":499},[235,15525,9690],{"class":1375},[235,15527,1976],{"class":499},[235,15529,15530,15533,15535,15537,15539,15542],{"class":237,"line":590},[235,15531,15532],{"class":519},"    console",[235,15534,1694],{"class":499},[235,15536,14802],{"class":252},[235,15538,1705],{"class":495},[235,15540,15541],{"class":519},"message",[235,15543,1953],{"class":495},[235,15545,15546],{"class":237,"line":604},[235,15547,1317],{"class":499},[13,15549,15550],{},"ちなみにbundle.jsは以下の通りに書かれていました。ES6の書き方がで出力されています。",[226,15552,15554],{"className":3990,"code":15553,"filename":14404,"language":3992,"meta":231,"style":231},"\u002F\u002F...\n\u002F\u002F const message = \\\"use in IE\\\";\\n()=>{\\n    console.log(message)\n\u002F\u002F...\n",[39,15555,15556,15560,15565],{"__ignoreMap":231},[235,15557,15558],{"class":237,"line":238},[235,15559,4211],{"class":3119},[235,15561,15562],{"class":237,"line":249},[235,15563,15564],{"class":3119},"\u002F\u002F const message = \\\"use in IE\\\";\\n()=>{\\n    console.log(message)\n",[235,15566,15567],{"class":237,"line":259},[235,15568,4211],{"class":3119},[81,15570,15572],{"id":15571},"モジュールをインストールしjsのruleを設定","モジュールをインストールし、JSのruleを設定",[13,15574,15575],{},"まずはloaderをインストールします。",[226,15577,15580],{"className":15578,"code":15579,"language":934},[932],"npm install -D babel-loader @babel\u002Fcore @babel\u002Fpreset-env\n",[39,15581,15579],{"__ignoreMap":231},[13,15583,15584,15585,15590,15591,15594],{},"そして",[197,15586,15589],{"href":15587,"rel":15588},"https:\u002F\u002Fwebpack.js.org\u002Floaders\u002Fbabel-loader\u002F",[201],"ドキュメントのまま","ですがJSファイルに対しての",[39,15592,15593],{},"rule","を追加し、babel-loaderを適用させる様にします。",[226,15596,15599],{"className":3990,"code":15597,"filename":15598,"language":3992,"meta":231,"style":231},"\u002F\u002F ...\nmodule: {\n    rules: [\n        \u002F\u002F 追加\n        {\n            test: \u002F\\.m?js$\u002F,\n            exclude: \u002F(node_modules|bower_components)\u002F,\n            use: {\n                loader: 'babel-loader',\n                options: {\n                    presets: ['@babel\u002Fpreset-env']\n                }\n            }\n        },\n        {\n            test: \u002F\\.(sa|sc|c)ss$\u002F,\n            exclude: \u002Fnode_modules\u002F,\n            use: [\n                MiniCssExtractPlugin.loader,\n                {\n                    loader: 'css-loader',\n                    options: { url: true }\n                },\n                'sass-loader',\n            ]\n        },\n        \u002F\u002F ...\n    ],\n},\n\u002F\u002F ...\n","webpack.comfig.js",[39,15600,15601,15606,15615,15623,15628,15632,15654,15672,15680,15694,15702,15719,15724,15728,15732,15736,15768,15782,15790,15801,15806,15820,15836,15840,15851,15856,15860,15865,15871,15875],{"__ignoreMap":231},[235,15602,15603],{"class":237,"line":238},[235,15604,15605],{"class":3119},"\u002F\u002F ...\n",[235,15607,15608,15611,15613],{"class":237,"line":249},[235,15609,15610],{"class":241},"module",[235,15612,500],{"class":499},[235,15614,1276],{"class":499},[235,15616,15617,15619,15621],{"class":237,"line":259},[235,15618,4192],{"class":241},[235,15620,500],{"class":499},[235,15622,1385],{"class":495},[235,15624,15625],{"class":237,"line":266},[235,15626,15627],{"class":3119},"        \u002F\u002F 追加\n",[235,15629,15630],{"class":237,"line":275},[235,15631,7136],{"class":499},[235,15633,15634,15636,15638,15640,15642,15644,15646,15648,15650,15652],{"class":237,"line":283},[235,15635,7141],{"class":495},[235,15637,500],{"class":499},[235,15639,4040],{"class":499},[235,15641,4043],{"class":519},[235,15643,7150],{"class":245},[235,15645,7153],{"class":499},[235,15647,1262],{"class":245},[235,15649,4052],{"class":1269},[235,15651,4055],{"class":499},[235,15653,1984],{"class":499},[235,15655,15656,15658,15660,15662,15664,15666,15668,15670],{"class":237,"line":291},[235,15657,7166],{"class":495},[235,15659,500],{"class":499},[235,15661,7171],{"class":499},[235,15663,5754],{"class":245},[235,15665,6729],{"class":499},[235,15667,7178],{"class":245},[235,15669,7181],{"class":499},[235,15671,1984],{"class":499},[235,15673,15674,15676,15678],{"class":237,"line":298},[235,15675,7188],{"class":495},[235,15677,500],{"class":499},[235,15679,1276],{"class":499},[235,15681,15682,15684,15686,15688,15690,15692],{"class":237,"line":380},[235,15683,6792],{"class":495},[235,15685,500],{"class":499},[235,15687,503],{"class":499},[235,15689,7204],{"class":245},[235,15691,1345],{"class":499},[235,15693,1984],{"class":499},[235,15695,15696,15698,15700],{"class":237,"line":465},[235,15697,6808],{"class":495},[235,15699,500],{"class":499},[235,15701,1276],{"class":499},[235,15703,15704,15707,15709,15711,15713,15715,15717],{"class":237,"line":590},[235,15705,15706],{"class":495},"                    presets",[235,15708,500],{"class":499},[235,15710,5192],{"class":495},[235,15712,1345],{"class":499},[235,15714,7231],{"class":245},[235,15716,1345],{"class":499},[235,15718,1444],{"class":495},[235,15720,15721],{"class":237,"line":604},[235,15722,15723],{"class":499},"                }\n",[235,15725,15726],{"class":237,"line":612},[235,15727,5812],{"class":499},[235,15729,15730],{"class":237,"line":623},[235,15731,5276],{"class":499},[235,15733,15734],{"class":237,"line":634},[235,15735,7136],{"class":499},[235,15737,15738,15740,15742,15744,15746,15748,15750,15752,15754,15756,15758,15760,15762,15764,15766],{"class":237,"line":641},[235,15739,7141],{"class":495},[235,15741,500],{"class":499},[235,15743,4040],{"class":499},[235,15745,4043],{"class":519},[235,15747,1705],{"class":499},[235,15749,6726],{"class":245},[235,15751,6729],{"class":499},[235,15753,6732],{"class":245},[235,15755,6729],{"class":499},[235,15757,6737],{"class":245},[235,15759,1715],{"class":499},[235,15761,6742],{"class":245},[235,15763,4052],{"class":1269},[235,15765,4055],{"class":499},[235,15767,1984],{"class":499},[235,15769,15770,15772,15774,15776,15778,15780],{"class":237,"line":653},[235,15771,7166],{"class":495},[235,15773,500],{"class":499},[235,15775,4040],{"class":499},[235,15777,5754],{"class":245},[235,15779,4055],{"class":499},[235,15781,1984],{"class":499},[235,15783,15784,15786,15788],{"class":237,"line":661},[235,15785,7188],{"class":495},[235,15787,500],{"class":499},[235,15789,1385],{"class":495},[235,15791,15792,15795,15797,15799],{"class":237,"line":670},[235,15793,15794],{"class":519},"                MiniCssExtractPlugin",[235,15796,1694],{"class":499},[235,15798,6780],{"class":519},[235,15800,1984],{"class":499},[235,15802,15803],{"class":237,"line":678},[235,15804,15805],{"class":499},"                {\n",[235,15807,15808,15810,15812,15814,15816,15818],{"class":237,"line":686},[235,15809,14207],{"class":495},[235,15811,500],{"class":499},[235,15813,503],{"class":499},[235,15815,6799],{"class":245},[235,15817,1345],{"class":499},[235,15819,1984],{"class":499},[235,15821,15822,15824,15826,15828,15830,15832,15834],{"class":237,"line":694},[235,15823,14222],{"class":495},[235,15825,500],{"class":499},[235,15827,6813],{"class":499},[235,15829,6816],{"class":495},[235,15831,500],{"class":499},[235,15833,5805],{"class":4702},[235,15835,6823],{"class":499},[235,15837,15838],{"class":237,"line":702},[235,15839,15154],{"class":499},[235,15841,15842,15845,15847,15849],{"class":237,"line":712},[235,15843,15844],{"class":499},"                '",[235,15846,6835],{"class":245},[235,15848,1345],{"class":499},[235,15850,1984],{"class":499},[235,15852,15853],{"class":237,"line":723},[235,15854,15855],{"class":495},"            ]\n",[235,15857,15858],{"class":237,"line":730},[235,15859,5276],{"class":499},[235,15861,15862],{"class":237,"line":741},[235,15863,15864],{"class":3119},"        \u002F\u002F ...\n",[235,15866,15867,15869],{"class":237,"line":752},[235,15868,14580],{"class":495},[235,15870,1984],{"class":499},[235,15872,15873],{"class":237,"line":763},[235,15874,1414],{"class":499},[235,15876,15877],{"class":237,"line":774},[235,15878,15605],{"class":3119},[13,15880,15881],{},"これでbabelが有効になり、トランスコンパイルされます。実際に動かしてみてbundle.jsをみてみると",[226,15883,15886],{"className":15884,"code":15885,"filename":14404,"language":934,"meta":231},[932],"var message = \\\"use in IE\\\";\\n\\n(function () {\\n  console.log(message);\\n})\n",[39,15887,15885],{"__ignoreMap":231},[13,15889,15890],{},"このようにES5の書き方に直してくれました。",[81,15892,15893],{"id":15893},"特定のビルドだけでトランスコンパイルしたい時",[13,15895,15896,15897,15900,15901,15904],{},"ちなみに今回は数行のコードなので十分ですが、本番では大量のファイルと記述を変換するので時間がかかったりメモリを食います。",[39,15898,15899],{},"npm run watch","でもそこそこメモリを食う様になります。対策としては環境変数を用いて本番ビルドの時だけトランスコンパイルさせる様にします。簡単な例としてまず",[39,15902,15903],{},"packge.json","でnode.jsの変数をコマンド上で定義します。",[226,15906,15908],{"className":12568,"code":15907,"filename":2966,"language":12570,"meta":231,"style":231},"  \"scripts\": {\n    \"build\": \"es5=true npx webpack-cli build\",\n    \"watch\": \"npx webpack-cli watch\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n",[39,15909,15910,15923,15943,15963,15992],{"__ignoreMap":231},[235,15911,15912,15914,15917,15919,15921],{"class":237,"line":238},[235,15913,12581],{"class":499},[235,15915,15916],{"class":245},"scripts",[235,15918,1517],{"class":499},[235,15920,14664],{"class":519},[235,15922,1976],{"class":499},[235,15924,15925,15927,15930,15932,15934,15936,15939,15941],{"class":237,"line":249},[235,15926,12817],{"class":499},[235,15928,15929],{"class":1375},"build",[235,15931,1517],{"class":499},[235,15933,500],{"class":499},[235,15935,595],{"class":499},[235,15937,15938],{"class":245},"es5=true npx webpack-cli build",[235,15940,1517],{"class":499},[235,15942,1984],{"class":499},[235,15944,15945,15947,15950,15952,15954,15956,15959,15961],{"class":237,"line":259},[235,15946,12817],{"class":499},[235,15948,15949],{"class":1375},"watch",[235,15951,1517],{"class":499},[235,15953,500],{"class":499},[235,15955,595],{"class":499},[235,15957,15958],{"class":245},"npx webpack-cli watch",[235,15960,1517],{"class":499},[235,15962,1984],{"class":499},[235,15964,15965,15967,15970,15972,15974,15976,15979,15982,15985,15987,15990],{"class":237,"line":266},[235,15966,12817],{"class":499},[235,15968,15969],{"class":1375},"test",[235,15971,1517],{"class":499},[235,15973,500],{"class":499},[235,15975,595],{"class":499},[235,15977,15978],{"class":245},"echo ",[235,15980,15981],{"class":519},"\\\"",[235,15983,15984],{"class":245},"Error: no test specified",[235,15986,15981],{"class":519},[235,15988,15989],{"class":245}," && exit 1",[235,15991,601],{"class":499},[235,15993,15994,15997],{"class":237,"line":275},[235,15995,15996],{"class":499},"  }",[235,15998,1984],{"class":519},[13,16000,16001,16002,16005,16006,16009,16010,16012],{},"今回の場合、",[39,16003,16004],{},"npm run build","した時に",[39,16007,16008],{},"es5=true","という変数が定義されます。そして",[39,16011,2046],{},"のrulesをこんな風に変更してみます。",[226,16014,16016],{"className":3990,"code":16015,"filename":15598,"language":3992,"meta":231,"style":231},"\u002F\u002F ...\n\u002F\u002F rulesを外で定義しておく。\nlet rules = [\n    {\n        test: \u002F\\.(sa|sc|c)ss$\u002F,\n        exclude: \u002Fnode_modules\u002F,\n        use: [\n            MiniCssExtractPlugin.loader,\n            {\n                loader: 'css-loader',\n                options: { url: true }\n            },\n            'sass-loader',\n        ]\n    },\n    {\n        test: \u002F\\.(png|jpg|gif)$\u002Fi,\n        generator: {\n            filename: 'imgs\u002F[name][ext][query]'\n        },\n        type: 'asset\u002Fresource'\n    }\n]\n\n\u002F\u002F es5がtrueならばバベルを適用\nif(process.env.es5){\n    rules.push(\n        {\n            test: \u002F\\.m?js$\u002F,\n            exclude: \u002F(node_modules|bower_components)\u002F,\n            use: {\n              loader: 'babel-loader',\n              options: {\n                presets: ['@babel\u002Fpreset-env']\n              }\n            }\n        }\n    )\n}\n\nmodule.exports = {\n    \u002F\u002Fバンドル対象のファイル\n    entry: '.\u002Fsrc\u002Fjs\u002Fmain.js',\n  \n    mode:\"development\",\n    \n    module: {\n        rules: rules\n    },\n\n    \u002F\u002F ...\n}\n",[39,16017,16018,16022,16027,16037,16041,16073,16087,16095,16105,16109,16123,16139,16143,16153,16157,16161,16165,16197,16205,16217,16221,16233,16237,16241,16245,16250,16266,16276,16280,16302,16320,16328,16342,16350,16366,16370,16374,16378,16382,16386,16390,16398,16402,16416,16420,16434,16438,16446,16454,16458,16462,16466],{"__ignoreMap":231},[235,16019,16020],{"class":237,"line":238},[235,16021,15605],{"class":3119},[235,16023,16024],{"class":237,"line":249},[235,16025,16026],{"class":3119},"\u002F\u002F rulesを外で定義しておく。\n",[235,16028,16029,16031,16033,16035],{"class":237,"line":259},[235,16030,4008],{"class":1375},[235,16032,4011],{"class":519},[235,16034,1382],{"class":499},[235,16036,1385],{"class":519},[235,16038,16039],{"class":237,"line":266},[235,16040,4030],{"class":499},[235,16042,16043,16045,16047,16049,16051,16053,16055,16057,16059,16061,16063,16065,16067,16069,16071],{"class":237,"line":275},[235,16044,4035],{"class":495},[235,16046,500],{"class":499},[235,16048,4040],{"class":499},[235,16050,4043],{"class":519},[235,16052,1705],{"class":499},[235,16054,6726],{"class":245},[235,16056,6729],{"class":499},[235,16058,6732],{"class":245},[235,16060,6729],{"class":499},[235,16062,6737],{"class":245},[235,16064,1715],{"class":499},[235,16066,6742],{"class":245},[235,16068,4052],{"class":1269},[235,16070,4055],{"class":499},[235,16072,1984],{"class":499},[235,16074,16075,16077,16079,16081,16083,16085],{"class":237,"line":283},[235,16076,5747],{"class":495},[235,16078,500],{"class":499},[235,16080,4040],{"class":499},[235,16082,5754],{"class":245},[235,16084,4055],{"class":499},[235,16086,1984],{"class":499},[235,16088,16089,16091,16093],{"class":237,"line":291},[235,16090,4062],{"class":495},[235,16092,500],{"class":499},[235,16094,1385],{"class":519},[235,16096,16097,16099,16101,16103],{"class":237,"line":298},[235,16098,6775],{"class":519},[235,16100,1694],{"class":499},[235,16102,6780],{"class":519},[235,16104,1984],{"class":499},[235,16106,16107],{"class":237,"line":380},[235,16108,6787],{"class":499},[235,16110,16111,16113,16115,16117,16119,16121],{"class":237,"line":465},[235,16112,6792],{"class":495},[235,16114,500],{"class":499},[235,16116,503],{"class":499},[235,16118,6799],{"class":245},[235,16120,1345],{"class":499},[235,16122,1984],{"class":499},[235,16124,16125,16127,16129,16131,16133,16135,16137],{"class":237,"line":590},[235,16126,6808],{"class":495},[235,16128,500],{"class":499},[235,16130,6813],{"class":499},[235,16132,6816],{"class":495},[235,16134,500],{"class":499},[235,16136,5805],{"class":4702},[235,16138,6823],{"class":499},[235,16140,16141],{"class":237,"line":604},[235,16142,6828],{"class":499},[235,16144,16145,16147,16149,16151],{"class":237,"line":612},[235,16146,5244],{"class":499},[235,16148,6835],{"class":245},[235,16150,1345],{"class":499},[235,16152,1984],{"class":499},[235,16154,16155],{"class":237,"line":623},[235,16156,5822],{"class":519},[235,16158,16159],{"class":237,"line":634},[235,16160,4091],{"class":499},[235,16162,16163],{"class":237,"line":641},[235,16164,4030],{"class":499},[235,16166,16167,16169,16171,16173,16175,16177,16179,16181,16183,16185,16187,16189,16191,16193,16195],{"class":237,"line":653},[235,16168,4035],{"class":495},[235,16170,500],{"class":499},[235,16172,4040],{"class":499},[235,16174,4043],{"class":519},[235,16176,1705],{"class":499},[235,16178,6869],{"class":245},[235,16180,6729],{"class":499},[235,16182,6874],{"class":245},[235,16184,6729],{"class":499},[235,16186,6879],{"class":245},[235,16188,1715],{"class":499},[235,16190,4052],{"class":1269},[235,16192,4055],{"class":499},[235,16194,6893],{"class":2836},[235,16196,1984],{"class":499},[235,16198,16199,16201,16203],{"class":237,"line":661},[235,16200,6900],{"class":495},[235,16202,500],{"class":499},[235,16204,1276],{"class":499},[235,16206,16207,16209,16211,16213,16215],{"class":237,"line":670},[235,16208,6909],{"class":495},[235,16210,500],{"class":499},[235,16212,503],{"class":499},[235,16214,15147],{"class":245},[235,16216,509],{"class":499},[235,16218,16219],{"class":237,"line":678},[235,16220,5276],{"class":499},[235,16222,16223,16225,16227,16229,16231],{"class":237,"line":686},[235,16224,6927],{"class":495},[235,16226,500],{"class":499},[235,16228,503],{"class":499},[235,16230,6934],{"class":245},[235,16232,509],{"class":499},[235,16234,16235],{"class":237,"line":694},[235,16236,2181],{"class":499},[235,16238,16239],{"class":237,"line":702},[235,16240,1444],{"class":519},[235,16242,16243],{"class":237,"line":712},[235,16244,263],{"emptyLinePlaceholder":262},[235,16246,16247],{"class":237,"line":723},[235,16248,16249],{"class":3119},"\u002F\u002F es5がtrueならばバベルを適用\n",[235,16251,16252,16254,16256,16258,16260,16262,16264],{"class":237,"line":730},[235,16253,7106],{"class":1269},[235,16255,7109],{"class":519},[235,16257,1694],{"class":499},[235,16259,7114],{"class":519},[235,16261,1694],{"class":499},[235,16263,7119],{"class":519},[235,16265,1976],{"class":499},[235,16267,16268,16270,16272,16274],{"class":237,"line":741},[235,16269,4192],{"class":519},[235,16271,1694],{"class":499},[235,16273,4606],{"class":252},[235,16275,4609],{"class":495},[235,16277,16278],{"class":237,"line":752},[235,16279,7136],{"class":499},[235,16281,16282,16284,16286,16288,16290,16292,16294,16296,16298,16300],{"class":237,"line":763},[235,16283,7141],{"class":495},[235,16285,500],{"class":499},[235,16287,4040],{"class":499},[235,16289,4043],{"class":519},[235,16291,7150],{"class":245},[235,16293,7153],{"class":499},[235,16295,1262],{"class":245},[235,16297,4052],{"class":1269},[235,16299,4055],{"class":499},[235,16301,1984],{"class":499},[235,16303,16304,16306,16308,16310,16312,16314,16316,16318],{"class":237,"line":774},[235,16305,7166],{"class":495},[235,16307,500],{"class":499},[235,16309,7171],{"class":499},[235,16311,5754],{"class":245},[235,16313,6729],{"class":499},[235,16315,7178],{"class":245},[235,16317,7181],{"class":499},[235,16319,1984],{"class":499},[235,16321,16322,16324,16326],{"class":237,"line":785},[235,16323,7188],{"class":495},[235,16325,500],{"class":499},[235,16327,1276],{"class":499},[235,16329,16330,16332,16334,16336,16338,16340],{"class":237,"line":794},[235,16331,7197],{"class":495},[235,16333,500],{"class":499},[235,16335,503],{"class":499},[235,16337,7204],{"class":245},[235,16339,1345],{"class":499},[235,16341,1984],{"class":499},[235,16343,16344,16346,16348],{"class":237,"line":806},[235,16345,7213],{"class":495},[235,16347,500],{"class":499},[235,16349,1276],{"class":499},[235,16351,16352,16354,16356,16358,16360,16362,16364],{"class":237,"line":815},[235,16353,7222],{"class":495},[235,16355,500],{"class":499},[235,16357,5192],{"class":495},[235,16359,1345],{"class":499},[235,16361,7231],{"class":245},[235,16363,1345],{"class":499},[235,16365,1444],{"class":495},[235,16367,16368],{"class":237,"line":823},[235,16369,7241],{"class":499},[235,16371,16372],{"class":237,"line":833},[235,16373,5812],{"class":499},[235,16375,16376],{"class":237,"line":3537},[235,16377,4086],{"class":499},[235,16379,16380],{"class":237,"line":3542},[235,16381,4715],{"class":495},[235,16383,16384],{"class":237,"line":3547},[235,16385,1317],{"class":499},[235,16387,16388],{"class":237,"line":3553},[235,16389,263],{"emptyLinePlaceholder":262},[235,16391,16392,16394,16396],{"class":237,"line":3558},[235,16393,4220],{"class":499},[235,16395,4116],{"class":499},[235,16397,1276],{"class":499},[235,16399,16400],{"class":237,"line":3564},[235,16401,13947],{"class":3119},[235,16403,16404,16406,16408,16410,16412,16414],{"class":237,"line":4},[235,16405,4123],{"class":495},[235,16407,500],{"class":499},[235,16409,503],{"class":499},[235,16411,4130],{"class":245},[235,16413,1345],{"class":499},[235,16415,1984],{"class":499},[235,16417,16418],{"class":237,"line":3575},[235,16419,4139],{"class":519},[235,16421,16422,16424,16426,16428,16430,16432],{"class":237,"line":3581},[235,16423,4144],{"class":495},[235,16425,500],{"class":499},[235,16427,1517],{"class":499},[235,16429,4151],{"class":245},[235,16431,1517],{"class":499},[235,16433,1984],{"class":499},[235,16435,16436],{"class":237,"line":3587},[235,16437,4160],{"class":519},[235,16439,16440,16442,16444],{"class":237,"line":3593},[235,16441,4165],{"class":495},[235,16443,500],{"class":499},[235,16445,1276],{"class":499},[235,16447,16448,16450,16452],{"class":237,"line":3599},[235,16449,4174],{"class":495},[235,16451,500],{"class":499},[235,16453,4179],{"class":519},[235,16455,16456],{"class":237,"line":3605},[235,16457,4091],{"class":499},[235,16459,16460],{"class":237,"line":3611},[235,16461,263],{"emptyLinePlaceholder":262},[235,16463,16464],{"class":237,"line":3616},[235,16465,4096],{"class":3119},[235,16467,16468],{"class":237,"line":3621},[235,16469,1317],{"class":499},[13,16471,16472,16474,16475,16477,16478,16481,16482,16484,16485,16487,16488,16490,16491,16493],{},[39,16473,3986],{},"を",[39,16476,4220],{},"の外に出しておいて、",[39,16479,16480],{},"process.env.es5","の値によって",[39,16483,3986],{},"を変更できる様にします。これで",[39,16486,3986],{},"の分岐ができました。",[39,16489,15929],{},"の時だけBabelが使用され、",[39,16492,15949],{},"の時はBabelが無しになります。この辺はプロジェクトごとに好きに設定してみてください。",[74,16495,13484],{"id":13484},[13,16497,16498],{},"最後に複数のバンドルファイルを出力する方法を解説します。今は参照されているアセットファイルを全てbundle.js、bundle.cssにしています。しかしプロジェクトによっては",[17,16500,16501,16504],{},[20,16502,16503],{},"一般ユーザーが閲覧するページのjs\u002Fcss",[20,16505,16506],{},"管理画面など特定のユーザーのみが使用するページのjs\u002Fcss",[13,16508,16509,16510,16513],{},"など複数パターンのファイルを出力したい時があります。例えば私はよく管理画面のUIはbootstrapとvueを使って構築してしまいます。そして一般画面はせいぜいjqueryを使用して200行にも満たないこともあります。管理画面はbootstrap合わせていろんなライブラリを使うため本番ビルドしてもかなりファイル容量を食います。一方、一般画面はそれほど大きくなりません。そんな時に全て一つの",[39,16511,16512],{},"bundle.js\u002Fcss","にまとめては一般画面に重いファイルを配ってしまいますし、場合によっては管理画面の構築コードが漏れてしまうのでよろしくありません。",[81,16515,16516],{"id":16516},"作成目標とsrcを作成",[13,16518,16519,16520,1404,16523,1209,16526,1404,16528,16531],{},"このような状況もよくあるので複数のバンドルファイルを出力できる様にしましょう。上記の様な状況として管理画面の",[39,16521,16522],{},"admin.js",[39,16524,16525],{},"admin.css",[39,16527,15369],{},[39,16529,16530],{},"main.css","が必要になったとしましょう。",[226,16533,16536],{"className":16534,"code":16535,"language":934},[932],".\n├── dist\n│   ├── admin.css   \u002F\u002F 作成目標\n│   ├── admin.js    \u002F\u002F 作成目標\n│   ├── imgs\n│   │   └── test.png\n│   ├── index.html\n│   ├── main.css    \u002F\u002F 作成目標\n│   └── main.js     \u002F\u002F 作成目標\n├── package-lock.json\n├── package.json\n├── node_modules\n├── src\n│   ├── imgs\n│   │   ├── sample.png\n│   │   └── test.png\n│   ├── js\n│   │   ├── admin.js    \u002F\u002F 作成\n│   │   ├── functions.js\n│   │   └── main.js\n│   └── sass\n│       ├── admin.scss  \u002F\u002F 作成\n│       ├── compnent.scss\n│       ├── style.scss\n│       ├── utility\n│       └── variable.scss\n└── webpack.config.js\n",[39,16537,16535],{"__ignoreMap":231},[13,16539,16540,16541,1404,16543,16546],{},"srcにエントリーとなる",[39,16542,16522],{},[39,16544,16545],{},"admin.scss","を作成します。中身は適当にadminのみで使われている記述にしてみてください。ここでは省きます。",[81,16548,16550],{"id":16549},"webpackconfigjsを設定","webpack.config.jsを設定",[13,16552,15584,16553,3710,16555,1404,16558,1404,16561,16563],{},[39,16554,2046],{},[39,16556,16557],{},"entry",[39,16559,16560],{},"output",[39,16562,4601],{},"を以下の様に変更します。",[226,16565,16567],{"className":3990,"code":16566,"filename":2046,"language":3992,"meta":231,"style":231},"module.exports = {\n    entry:{\n        main:'.\u002Fsrc\u002Fjs\u002Fmain.js',\n        admin:'.\u002Fsrc\u002Fjs\u002Fadmin.js'\n    },\n\n    \u002F\u002F 省略\n\n    output: {\n        \u002F\u002F  出力ファイルのディレクトリ名\n        path: `${__dirname}\u002Fdist`,\n        \u002F\u002F 出力ファイル名\n        filename: \"[name].js\"\n    },\n    plugins: [\n        new MiniCssExtractPlugin({\n            filename: '[name].css'\n        })\n    ]\n};\n",[39,16568,16569,16577,16583,16598,16612,16616,16620,16625,16629,16637,16641,16659,16663,16675,16679,16687,16697,16709,16715,16719],{"__ignoreMap":231},[235,16570,16571,16573,16575],{"class":237,"line":238},[235,16572,4220],{"class":499},[235,16574,4116],{"class":499},[235,16576,1276],{"class":499},[235,16578,16579,16581],{"class":237,"line":249},[235,16580,4123],{"class":495},[235,16582,5182],{"class":499},[235,16584,16585,16588,16590,16592,16594,16596],{"class":237,"line":259},[235,16586,16587],{"class":495},"        main",[235,16589,500],{"class":499},[235,16591,1345],{"class":499},[235,16593,4130],{"class":245},[235,16595,1345],{"class":499},[235,16597,1984],{"class":499},[235,16599,16600,16603,16605,16607,16610],{"class":237,"line":266},[235,16601,16602],{"class":495},"        admin",[235,16604,500],{"class":499},[235,16606,1345],{"class":499},[235,16608,16609],{"class":245},".\u002Fsrc\u002Fjs\u002Fadmin.js",[235,16611,509],{"class":499},[235,16613,16614],{"class":237,"line":275},[235,16615,4091],{"class":499},[235,16617,16618],{"class":237,"line":283},[235,16619,263],{"emptyLinePlaceholder":262},[235,16621,16622],{"class":237,"line":291},[235,16623,16624],{"class":3119},"    \u002F\u002F 省略\n",[235,16626,16627],{"class":237,"line":298},[235,16628,263],{"emptyLinePlaceholder":262},[235,16630,16631,16633,16635],{"class":237,"line":380},[235,16632,7521],{"class":495},[235,16634,500],{"class":499},[235,16636,1276],{"class":499},[235,16638,16639],{"class":237,"line":465},[235,16640,7531],{"class":3119},[235,16642,16643,16645,16647,16649,16651,16653,16655,16657],{"class":237,"line":590},[235,16644,7537],{"class":495},[235,16646,500],{"class":499},[235,16648,4631],{"class":499},[235,16650,7544],{"class":519},[235,16652,1950],{"class":499},[235,16654,7549],{"class":245},[235,16656,7552],{"class":499},[235,16658,1984],{"class":499},[235,16660,16661],{"class":237,"line":604},[235,16662,14393],{"class":3119},[235,16664,16665,16667,16669,16671,16673],{"class":237,"line":612},[235,16666,4626],{"class":495},[235,16668,500],{"class":499},[235,16670,595],{"class":499},[235,16672,7269],{"class":245},[235,16674,601],{"class":499},[235,16676,16677],{"class":237,"line":623},[235,16678,4091],{"class":499},[235,16680,16681,16683,16685],{"class":237,"line":634},[235,16682,7580],{"class":495},[235,16684,500],{"class":499},[235,16686,1385],{"class":519},[235,16688,16689,16691,16693,16695],{"class":237,"line":641},[235,16690,7590],{"class":499},[235,16692,7593],{"class":252},[235,16694,1705],{"class":519},[235,16696,1976],{"class":499},[235,16698,16699,16701,16703,16705,16707],{"class":237,"line":653},[235,16700,6909],{"class":495},[235,16702,500],{"class":499},[235,16704,503],{"class":499},[235,16706,7609],{"class":245},[235,16708,509],{"class":499},[235,16710,16711,16713],{"class":237,"line":661},[235,16712,7617],{"class":499},[235,16714,1953],{"class":519},[235,16716,16717],{"class":237,"line":670},[235,16718,7627],{"class":519},[235,16720,16721],{"class":237,"line":678},[235,16722,7633],{"class":499},[13,16724,16725,16726,3802],{},"注目して欲しいのは",[39,16727,16557],{},[226,16729,16731],{"className":3990,"code":16730,"language":3992,"meta":231,"style":231},"\u002F\u002F 変更前\nentry: '.\u002Fsrc\u002Fjs\u002Fmain.js',\n\n\u002F\u002F 変更後\nentry:{\n    main:'.\u002Fsrc\u002Fjs\u002Fmain.js',\n    admin:'.\u002Fsrc\u002Fjs\u002Fadmin.js'\n},\n",[39,16732,16733,16738,16752,16756,16761,16767,16782,16795],{"__ignoreMap":231},[235,16734,16735],{"class":237,"line":238},[235,16736,16737],{"class":3119},"\u002F\u002F 変更前\n",[235,16739,16740,16742,16744,16746,16748,16750],{"class":237,"line":249},[235,16741,16557],{"class":241},[235,16743,500],{"class":499},[235,16745,503],{"class":499},[235,16747,4130],{"class":245},[235,16749,1345],{"class":499},[235,16751,1984],{"class":499},[235,16753,16754],{"class":237,"line":259},[235,16755,263],{"emptyLinePlaceholder":262},[235,16757,16758],{"class":237,"line":266},[235,16759,16760],{"class":3119},"\u002F\u002F 変更後\n",[235,16762,16763,16765],{"class":237,"line":275},[235,16764,16557],{"class":241},[235,16766,5182],{"class":499},[235,16768,16769,16772,16774,16776,16778,16780],{"class":237,"line":283},[235,16770,16771],{"class":241},"    main",[235,16773,500],{"class":499},[235,16775,1345],{"class":499},[235,16777,4130],{"class":245},[235,16779,1345],{"class":499},[235,16781,1984],{"class":499},[235,16783,16784,16787,16789,16791,16793],{"class":237,"line":291},[235,16785,16786],{"class":241},"    admin",[235,16788,500],{"class":499},[235,16790,1345],{"class":499},[235,16792,16609],{"class":245},[235,16794,509],{"class":499},[235,16796,16797],{"class":237,"line":298},[235,16798,1414],{"class":499},[13,16800,16801,16802,16805,16806,16808],{},"今まではそれぞれのファイルを直接配列で指定してましたが、変更後ではオブジェクトにしています。オブジェクトのキーは",[39,16803,16804],{},"[name]","として利用できます。例えば、",[39,16807,16560],{},"でこの様に利用します。",[226,16810,16812],{"className":3990,"code":16811,"language":3992,"meta":231,"style":231},"output: {\n    \u002F\u002F  出力ファイルのディレクトリ名\n    path: `${__dirname}\u002Fdist`,\n    \u002F\u002F 出力ファイル名\n    filename: \"[name].js\"\n},\nplugins: [\n    new MiniCssExtractPlugin({\n        filename: '[name].css'\n    })\n]\n",[39,16813,16814,16822,16827,16846,16851,16864,16868,16876,16887,16899,16905],{"__ignoreMap":231},[235,16815,16816,16818,16820],{"class":237,"line":238},[235,16817,16560],{"class":241},[235,16819,500],{"class":499},[235,16821,1276],{"class":499},[235,16823,16824],{"class":237,"line":249},[235,16825,16826],{"class":3119},"    \u002F\u002F  出力ファイルのディレクトリ名\n",[235,16828,16829,16832,16834,16836,16838,16840,16842,16844],{"class":237,"line":259},[235,16830,16831],{"class":241},"    path",[235,16833,500],{"class":499},[235,16835,4631],{"class":499},[235,16837,7544],{"class":519},[235,16839,1950],{"class":499},[235,16841,7549],{"class":245},[235,16843,7552],{"class":499},[235,16845,1984],{"class":499},[235,16847,16848],{"class":237,"line":266},[235,16849,16850],{"class":3119},"    \u002F\u002F 出力ファイル名\n",[235,16852,16853,16856,16858,16860,16862],{"class":237,"line":275},[235,16854,16855],{"class":241},"    filename",[235,16857,500],{"class":499},[235,16859,595],{"class":499},[235,16861,7269],{"class":245},[235,16863,601],{"class":499},[235,16865,16866],{"class":237,"line":283},[235,16867,1414],{"class":499},[235,16869,16870,16872,16874],{"class":237,"line":291},[235,16871,4601],{"class":241},[235,16873,500],{"class":499},[235,16875,1385],{"class":519},[235,16877,16878,16881,16883,16885],{"class":237,"line":298},[235,16879,16880],{"class":499},"    new",[235,16882,7593],{"class":252},[235,16884,1705],{"class":519},[235,16886,1976],{"class":499},[235,16888,16889,16891,16893,16895,16897],{"class":237,"line":380},[235,16890,4626],{"class":495},[235,16892,500],{"class":499},[235,16894,503],{"class":499},[235,16896,7609],{"class":245},[235,16898,509],{"class":499},[235,16900,16901,16903],{"class":237,"line":465},[235,16902,13358],{"class":499},[235,16904,1953],{"class":519},[235,16906,16907],{"class":237,"line":590},[235,16908,1444],{"class":519},[13,16910,16911,16912,1404,16914,16916,16917,13843,16919,16921,16922,13843,16924,13843,16926,13843,16928,16930],{},"変更前は全て",[39,16913,14404],{},[39,16915,14439],{},"と一定の名前でしたが、こうするとオブジェクトのキー名に応じて、",[39,16918,15369],{},[39,16920,16522],{},"など作成されます。実際にビルドをしてみると、",[39,16923,15369],{},[39,16925,16522],{},[39,16927,16530],{},[39,16929,16525],{},"が作成されました。",[74,16932,6594],{"id":6593},[13,16934,16935],{},"以上が今回の内容です。画像・Babelそして複数ファイルパターンができればもうプロジェクトで十分利用可能です。次回はhtmlをsrc配下で利用できるようにします。src配下のみで作業してコマンド打って完成したファイルがdistに出せる様にします。そしてまとめとしてこれらの構成とpugを使用したプロトタイプページの作成をしてみます。",[2399,16937,16938],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .s6YsC, html code.shiki .s6YsC{--shiki-default:#B2CCD6}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .sbqyR, html code.shiki .sbqyR{--shiki-default:#FF9CAC}",{"title":231,"searchDepth":259,"depth":259,"links":16940},[16941,16951,16955,16959],{"id":13490,"depth":249,"text":13490,"children":16942},[16943,16944,16945,16950],{"id":13493,"depth":259,"text":13493},{"id":13836,"depth":259,"text":13836},{"id":13863,"depth":259,"text":13863,"children":16946},[16947,16948,16949],{"id":13866,"depth":266,"text":13866},{"id":14461,"depth":266,"text":14461},{"id":14628,"depth":266,"text":14628},{"id":14828,"depth":259,"text":14828},{"id":13481,"depth":249,"text":13481,"children":16952},[16953,16954],{"id":15571,"depth":259,"text":15572},{"id":15893,"depth":259,"text":15893},{"id":13484,"depth":249,"text":13484,"children":16956},[16957,16958],{"id":16516,"depth":259,"text":16516},{"id":16549,"depth":259,"text":16550},{"id":6593,"depth":249,"text":6594},[2427],"2021-06-06","Babel、画像の処理と複数バンドル",{},"\u002Fseries\u002Fwell-study-webpack-2",{"title":3891,"description":16962},"series\u002Fwell-study-webpack-2",[1262,7957],"HmfkSL8RL8-q0C9UnXt7ExxZBfF5TgF206dj6ahXmq8",{"id":16970,"title":16971,"body":16972,"category":18596,"createdAt":18597,"description":18598,"extension":2430,"index":2439,"meta":18599,"navigation":262,"path":18600,"publish":262,"seo":18601,"series":2439,"seriesTitle":2439,"stem":18602,"tag":18603,"thumbnail":18605,"updatedAt":2439,"__hash__":18606},"articles\u002Farticles\u002Fimplement-recaptcha.md","reCAPTCHAのフロントエンド実装とバックエンド実装（PHP・Laravel）をスクラッチで行う方法",{"type":10,"value":16973,"toc":18582},[16974,16977,16980,16983,16986,16990,16993,16996,16999,17002,17006,17015,17018,17025,17028,17031,17042,17045,17048,17214,17217,17228,17237,17241,17244,17480,17493,17496,17499,17969,17980,18002,18005,18008,18011,18014,18025,18028,18210,18221,18245,18261,18264,18302,18313,18316,18319,18364,18371,18374,18382,18407,18415,18424,18432,18438,18446,18449,18567,18570,18573,18576,18579],[13,16975,16976],{},"こんにちはjunです。皆さんはフォームを作成する時にBot・スパム対策を行っていますか？フォームというのは少し知識があれば、簡単にbot的に送信することができます。",[13,16978,16979],{},"curlでPOSTすることもあれば、javascriptを実行して機械的にフォームを送信することがきるので、スパム（嫌がらせ）やサーバーへの過剰負荷の原因となります。",[13,16981,16982],{},"この様な機械的な操作を防ぐために、よく「ロボットではありません」「画像に表示されている文字を入力してください」みたいなbotでは簡単に処理できないものを用意します。",[13,16984,16985],{},"しかしこの様な機能は自分で実装するのは大変です。そんな時に便利なのがreCAPTCHAです。",[74,16987,16989],{"id":16988},"recaptchaとは","reCAPTCHAとは？",[13,16991,16992],{},"reCAPTCHAはGoogleが無料で提供しているBot対策ツールです。現在v3までリリースされており、v2は画像を選択させたりチェックを入れるといったユーザーのアクションでbotかどうかを検証します。v3はその様なアクションを必要とせず、必要なスクリプトを入れるだけで検証ができます。これからの実装の場合はv3を入れることをお勧めします。",[74,16994,16995],{"id":16995},"実装内容",[13,16997,16998],{},"今回の解説ではv3でのフロントエンドの実装とバックエンドの実装を解説していきます。そして利用するreCAPTCHAはエンタープライズではなく、無料のものを利用します。バックエンドにはLaravel6(php)を用いて説明します。バックエンドは基本的にやることはどの言語・フレームワークでも特に差異はありません。reCAPTCHAを使う時にライブラリを使用することもありますが、いうてそれほど難しくないので今回はライブラリを使用しないスクラッチで実装します。",[13,17000,17001],{},"それでは解説を始めます。",[74,17003,17005],{"id":17004},"recaptchaのキーを手に入れる","reCAPTCHAのキーを手に入れる",[13,17007,17008,17009,17014],{},"reCAPTCHAはGooglenのAPIを使用することでbotか検証を行います。reCAPTCHAを利用するためにGoogleアカウントとreCAPTCHAのキーを登録します。",[197,17010,17013],{"href":17011,"rel":17012},"https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fadmin\u002Fcreate",[201],"reCAPTCHAの登録ページ","にて保護対象のドメインを設定します。",[183,17016],{":src":17017,":width":3011},"'_mix\u002Fsch-2021-05-21 23.16.06.png'",[13,17019,17020,17021,17024],{},"ラベルは管理用の名前、タイプはv3を使用します。保護対象のドメインを登録します。ドメインは複数設定できます。この時、本番のドメインと",[39,17022,17023],{},"localhost","を登録しておくと開発・本番で利用できます。",[13,17026,17027],{},"設定を終わって「保存」しますと、キーが表示されますので保存しておきます。",[183,17029],{":src":17030,":width":3011},"'_mix\u002Frecaptcha-key.jpeg'",[13,17032,17033,17037,17038,17041],{},[17034,17035,17036],"em",{},"このサイトキーは、ユーザー表示するHTMLコードで利用します。"," という方のキーはタグで利用し、正直みられても問題ありません。フロント側のキーはドメインと合わせて保護対処のサイトであるかのチェックのためにあるだけだからです。逆にバックの方である ",[17034,17039,17040],{},"このサイトキーは、サイトとreCAPTCHA間の通信で利用します。"," は漏れてはいけません。",[74,17043,17044],{"id":17044},"フロントエンドの実装",[13,17046,17047],{},"それではフロントエンドを実装していきます。かなり簡略化して書いています。以下の様なフォームがあったとしましょう。",[226,17049,17051],{"className":5051,"code":17050,"language":3947,"meta":231,"style":231},"\u003C!DOCTYPE html>\n\u003Chtml>\n    \u003Chead>\n      \u003C!---省略-->\n    \u003C\u002Fhead>\n\n    \u003Cbody>\n        \u003Cform method=\"post\">\n            \u003Cinput type=\"text\" name=\"test\" value=\"\">\n            \u003Cinput type=\"submit\" value=\"送信\">\n        \u003C\u002Fform>\n    \u003C\u002Fbody>\n\u003C\u002Fhtml>\n",[39,17052,17053,17063,17071,17079,17084,17092,17096,17104,17125,17160,17190,17198,17206],{"__ignoreMap":231},[235,17054,17055,17057,17059,17061],{"class":237,"line":238},[235,17056,9071],{"class":499},[235,17058,9074],{"class":495},[235,17060,6275],{"class":1375},[235,17062,1487],{"class":499},[235,17064,17065,17067,17069],{"class":237,"line":249},[235,17066,1481],{"class":499},[235,17068,3947],{"class":495},[235,17070,1487],{"class":499},[235,17072,17073,17075,17077],{"class":237,"line":259},[235,17074,1492],{"class":499},[235,17076,9093],{"class":495},[235,17078,1487],{"class":499},[235,17080,17081],{"class":237,"line":266},[235,17082,17083],{"class":3119},"      \u003C!---省略-->\n",[235,17085,17086,17088,17090],{"class":237,"line":275},[235,17087,1539],{"class":499},[235,17089,9093],{"class":495},[235,17091,1487],{"class":499},[235,17093,17094],{"class":237,"line":283},[235,17095,263],{"emptyLinePlaceholder":262},[235,17097,17098,17100,17102],{"class":237,"line":291},[235,17099,1492],{"class":499},[235,17101,4677],{"class":495},[235,17103,1487],{"class":499},[235,17105,17106,17108,17111,17114,17116,17118,17121,17123],{"class":237,"line":298},[235,17107,1506],{"class":499},[235,17109,17110],{"class":495},"form",[235,17112,17113],{"class":1375}," method",[235,17115,1382],{"class":499},[235,17117,1517],{"class":499},[235,17119,17120],{"class":245},"post",[235,17122,1517],{"class":499},[235,17124,1487],{"class":499},[235,17126,17127,17129,17131,17133,17135,17137,17139,17141,17144,17146,17148,17150,17152,17154,17156,17158],{"class":237,"line":380},[235,17128,9208],{"class":499},[235,17130,13693],{"class":495},[235,17132,9310],{"class":1375},[235,17134,1382],{"class":499},[235,17136,1517],{"class":499},[235,17138,934],{"class":245},[235,17140,1517],{"class":499},[235,17142,17143],{"class":1375}," name",[235,17145,1382],{"class":499},[235,17147,1517],{"class":499},[235,17149,15969],{"class":245},[235,17151,1517],{"class":499},[235,17153,13706],{"class":1375},[235,17155,1382],{"class":499},[235,17157,13711],{"class":499},[235,17159,1487],{"class":499},[235,17161,17162,17164,17166,17168,17170,17172,17175,17177,17179,17181,17183,17186,17188],{"class":237,"line":465},[235,17163,9208],{"class":499},[235,17165,13693],{"class":495},[235,17167,9310],{"class":1375},[235,17169,1382],{"class":499},[235,17171,1517],{"class":499},[235,17173,17174],{"class":245},"submit",[235,17176,1517],{"class":499},[235,17178,13706],{"class":1375},[235,17180,1382],{"class":499},[235,17182,1517],{"class":499},[235,17184,17185],{"class":245},"送信",[235,17187,1517],{"class":499},[235,17189,1487],{"class":499},[235,17191,17192,17194,17196],{"class":237,"line":590},[235,17193,9278],{"class":499},[235,17195,17110],{"class":495},[235,17197,1487],{"class":499},[235,17199,17200,17202,17204],{"class":237,"line":604},[235,17201,1539],{"class":499},[235,17203,4677],{"class":495},[235,17205,1487],{"class":499},[235,17207,17208,17210,17212],{"class":237,"line":612},[235,17209,1530],{"class":499},[235,17211,3947],{"class":495},[235,17213,1487],{"class":499},[13,17215,17216],{},"reCAPTCHAのフロントエンド 実装では",[17,17218,17219,17222,17225],{},[20,17220,17221],{},"reCAPTCHAのソースを読み込む",[20,17223,17224],{},"送信ボタンを押したらreCAPTCHAと通信してトークンを手に入れるスクリプトを書く",[20,17226,17227],{},"reCAPTCHAのトークンをフォーム内容と一緒にバックエンドに送信する。",[13,17229,17230,17231,17236],{},"以上の実装を必要とします。",[197,17232,17235],{"href":17233,"rel":17234},"https:\u002F\u002Fdevelopers.google.com\u002Frecaptcha\u002Fdocs\u002Fv3#programmatically_invoke_the_challenge",[201],"本家のドキュメント","を参考にして進めていきましょう。",[81,17238,17240],{"id":17239},"recaptchaのスクリプト読み込みとhtml調整","reCAPTCHAのスクリプト読み込みとHTML調整",[13,17242,17243],{},"まずはreCAPTCHAを有効にするためのスクリプトを読み込みます。そして一部フォームを編集します。",[226,17245,17247],{"className":5051,"code":17246,"language":3947,"meta":231,"style":231},"\u003C!DOCTYPE html>\n\u003Chtml>\n    \u003Chead>\n      \u003C!---省略-->\n        \u003Cscript src=\"https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fapi.js?render=YOUR_FRONT_KEY\">\u003C\u002Fscript>\u003C!---追加-->\n    \u003C\u002Fhead>\n\n    \u003Cbody>\n        \u003Cform method=\"post\" id=\"test-form\">\u003C!---追加-->\n            \u003Cinput type=\"text\" name=\"test\" value=\"\">\n            \u003Cinput type=\"hidden\" name=\"recaptcha\" value=\"\">\u003C!---追加-->\n            \u003Cinput type=\"submit\" value=\"送信\">\n        \u003C\u002Fform>\n    \u003C\u002Fbody>\n\u003C\u002Fhtml>\n",[39,17248,17249,17259,17267,17275,17279,17305,17313,17317,17325,17356,17390,17428,17456,17464,17472],{"__ignoreMap":231},[235,17250,17251,17253,17255,17257],{"class":237,"line":238},[235,17252,9071],{"class":499},[235,17254,9074],{"class":495},[235,17256,6275],{"class":1375},[235,17258,1487],{"class":499},[235,17260,17261,17263,17265],{"class":237,"line":249},[235,17262,1481],{"class":499},[235,17264,3947],{"class":495},[235,17266,1487],{"class":499},[235,17268,17269,17271,17273],{"class":237,"line":259},[235,17270,1492],{"class":499},[235,17272,9093],{"class":495},[235,17274,1487],{"class":499},[235,17276,17277],{"class":237,"line":266},[235,17278,17083],{"class":3119},[235,17280,17281,17283,17285,17287,17289,17291,17294,17296,17298,17300,17302],{"class":237,"line":275},[235,17282,1506],{"class":499},[235,17284,1558],{"class":495},[235,17286,5069],{"class":1375},[235,17288,1382],{"class":499},[235,17290,1517],{"class":499},[235,17292,17293],{"class":245},"https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fapi.js?render=YOUR_FRONT_KEY",[235,17295,1517],{"class":499},[235,17297,8809],{"class":499},[235,17299,1558],{"class":495},[235,17301,1524],{"class":499},[235,17303,17304],{"class":3119},"\u003C!---追加-->\n",[235,17306,17307,17309,17311],{"class":237,"line":283},[235,17308,1539],{"class":499},[235,17310,9093],{"class":495},[235,17312,1487],{"class":499},[235,17314,17315],{"class":237,"line":291},[235,17316,263],{"emptyLinePlaceholder":262},[235,17318,17319,17321,17323],{"class":237,"line":298},[235,17320,1492],{"class":499},[235,17322,4677],{"class":495},[235,17324,1487],{"class":499},[235,17326,17327,17329,17331,17333,17335,17337,17339,17341,17343,17345,17347,17350,17352,17354],{"class":237,"line":380},[235,17328,1506],{"class":499},[235,17330,17110],{"class":495},[235,17332,17113],{"class":1375},[235,17334,1382],{"class":499},[235,17336,1517],{"class":499},[235,17338,17120],{"class":245},[235,17340,1517],{"class":499},[235,17342,8017],{"class":1375},[235,17344,1382],{"class":499},[235,17346,1517],{"class":499},[235,17348,17349],{"class":245},"test-form",[235,17351,1517],{"class":499},[235,17353,1524],{"class":499},[235,17355,17304],{"class":3119},[235,17357,17358,17360,17362,17364,17366,17368,17370,17372,17374,17376,17378,17380,17382,17384,17386,17388],{"class":237,"line":465},[235,17359,9208],{"class":499},[235,17361,13693],{"class":495},[235,17363,9310],{"class":1375},[235,17365,1382],{"class":499},[235,17367,1517],{"class":499},[235,17369,934],{"class":245},[235,17371,1517],{"class":499},[235,17373,17143],{"class":1375},[235,17375,1382],{"class":499},[235,17377,1517],{"class":499},[235,17379,15969],{"class":245},[235,17381,1517],{"class":499},[235,17383,13706],{"class":1375},[235,17385,1382],{"class":499},[235,17387,13711],{"class":499},[235,17389,1487],{"class":499},[235,17391,17392,17394,17396,17398,17400,17402,17405,17407,17409,17411,17413,17416,17418,17420,17422,17424,17426],{"class":237,"line":590},[235,17393,9208],{"class":499},[235,17395,13693],{"class":495},[235,17397,9310],{"class":1375},[235,17399,1382],{"class":499},[235,17401,1517],{"class":499},[235,17403,17404],{"class":245},"hidden",[235,17406,1517],{"class":499},[235,17408,17143],{"class":1375},[235,17410,1382],{"class":499},[235,17412,1517],{"class":499},[235,17414,17415],{"class":245},"recaptcha",[235,17417,1517],{"class":499},[235,17419,13706],{"class":1375},[235,17421,1382],{"class":499},[235,17423,13711],{"class":499},[235,17425,1524],{"class":499},[235,17427,17304],{"class":3119},[235,17429,17430,17432,17434,17436,17438,17440,17442,17444,17446,17448,17450,17452,17454],{"class":237,"line":604},[235,17431,9208],{"class":499},[235,17433,13693],{"class":495},[235,17435,9310],{"class":1375},[235,17437,1382],{"class":499},[235,17439,1517],{"class":499},[235,17441,17174],{"class":245},[235,17443,1517],{"class":499},[235,17445,13706],{"class":1375},[235,17447,1382],{"class":499},[235,17449,1517],{"class":499},[235,17451,17185],{"class":245},[235,17453,1517],{"class":499},[235,17455,1487],{"class":499},[235,17457,17458,17460,17462],{"class":237,"line":612},[235,17459,9278],{"class":499},[235,17461,17110],{"class":495},[235,17463,1487],{"class":499},[235,17465,17466,17468,17470],{"class":237,"line":623},[235,17467,1539],{"class":499},[235,17469,4677],{"class":495},[235,17471,1487],{"class":499},[235,17473,17474,17476,17478],{"class":237,"line":634},[235,17475,1530],{"class":499},[235,17477,3947],{"class":495},[235,17479,1487],{"class":499},[13,17481,17482,3710,17485,17488,17489,17492],{},[39,17483,17484],{},"\u003Cscript src=\"https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fapi.js?render=YOUR_FRONT_KEY\">\u003C\u002Fscript>",[39,17486,17487],{},"YOUR_FRONT_KEY","に先ほど取得したフロント用のキーを入れます。\n",[39,17490,17491],{},"\u003Cinput type=\"hidden\" name=\"recaptcha\" value=\"\">","にはreCAPTCHAのトークンを挿入してバックエンドに送ります。HTMLフォームであればこの様にしますが、axiosなどの場合はトークンの値をjsを用いて送信するので、このHTMLは要りません。",[81,17494,17495],{"id":17495},"トークンを取得するスクリプトを記述",[13,17497,17498],{},"「送信ボタン」を押した時にreCAPTCHAにAPIを飛ばしてbotかどうかの判定用トークンを取得します。以下の様なスクリプトを記述します。",[226,17500,17502],{"className":5051,"code":17501,"language":3947,"meta":231,"style":231},"\u003C!DOCTYPE html>\n\u003Chtml>\n    \u003Chead>\n      \u003C!---省略-->\n      \u003Cscript src=\"https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fapi.js?render=YOUR_FRONT_KEY\">\u003C\u002Fscript>\n    \u003C\u002Fhead>\n\n    \u003Cbody>\n        \u003Cform method=\"post\" id=\"test-form\">\u003C!---追加-->\n            \u003Cinput type=\"text\" name=\"test\" value=\"\">\n            \u003Cinput type=\"hidden\" name=\"recaptcha\" value=\"\">\u003C!---追加-->\n            \u003Cinput type=\"submit\" value=\"送信\">\n        \u003C\u002Fform>\n    \u003C\u002Fbody>\n\n    \u003Cscript>\n        function checkCaptcha(e) {\n            e.preventDefault();\n            grecaptcha.ready(function() {\n                grecaptcha.execute('YOUR_FRONT_KEY', {action: 'submit'}).then(function(token) {\n                    document.getElementById(\"recaptcha\").value=token;\n                    document.getElementById(\"test-form\").submit();\n                });\n            });\n        }\n        document.getElementById(\"test-form\").addEventListener('submit', checkCaptcha);\n        \u003C\u002Fscript>\n\u003C\u002Fhtml>\n",[39,17503,17504,17514,17522,17530,17534,17557,17565,17569,17577,17607,17641,17677,17705,17713,17721,17725,17733,17750,17764,17783,17837,17867,17893,17902,17911,17915,17953,17961],{"__ignoreMap":231},[235,17505,17506,17508,17510,17512],{"class":237,"line":238},[235,17507,9071],{"class":499},[235,17509,9074],{"class":495},[235,17511,6275],{"class":1375},[235,17513,1487],{"class":499},[235,17515,17516,17518,17520],{"class":237,"line":249},[235,17517,1481],{"class":499},[235,17519,3947],{"class":495},[235,17521,1487],{"class":499},[235,17523,17524,17526,17528],{"class":237,"line":259},[235,17525,1492],{"class":499},[235,17527,9093],{"class":495},[235,17529,1487],{"class":499},[235,17531,17532],{"class":237,"line":266},[235,17533,17083],{"class":3119},[235,17535,17536,17539,17541,17543,17545,17547,17549,17551,17553,17555],{"class":237,"line":275},[235,17537,17538],{"class":499},"      \u003C",[235,17540,1558],{"class":495},[235,17542,5069],{"class":1375},[235,17544,1382],{"class":499},[235,17546,1517],{"class":499},[235,17548,17293],{"class":245},[235,17550,1517],{"class":499},[235,17552,8809],{"class":499},[235,17554,1558],{"class":495},[235,17556,1487],{"class":499},[235,17558,17559,17561,17563],{"class":237,"line":283},[235,17560,1539],{"class":499},[235,17562,9093],{"class":495},[235,17564,1487],{"class":499},[235,17566,17567],{"class":237,"line":291},[235,17568,263],{"emptyLinePlaceholder":262},[235,17570,17571,17573,17575],{"class":237,"line":298},[235,17572,1492],{"class":499},[235,17574,4677],{"class":495},[235,17576,1487],{"class":499},[235,17578,17579,17581,17583,17585,17587,17589,17591,17593,17595,17597,17599,17601,17603,17605],{"class":237,"line":380},[235,17580,1506],{"class":499},[235,17582,17110],{"class":495},[235,17584,17113],{"class":1375},[235,17586,1382],{"class":499},[235,17588,1517],{"class":499},[235,17590,17120],{"class":245},[235,17592,1517],{"class":499},[235,17594,8017],{"class":1375},[235,17596,1382],{"class":499},[235,17598,1517],{"class":499},[235,17600,17349],{"class":245},[235,17602,1517],{"class":499},[235,17604,1524],{"class":499},[235,17606,17304],{"class":3119},[235,17608,17609,17611,17613,17615,17617,17619,17621,17623,17625,17627,17629,17631,17633,17635,17637,17639],{"class":237,"line":465},[235,17610,9208],{"class":499},[235,17612,13693],{"class":495},[235,17614,9310],{"class":1375},[235,17616,1382],{"class":499},[235,17618,1517],{"class":499},[235,17620,934],{"class":245},[235,17622,1517],{"class":499},[235,17624,17143],{"class":1375},[235,17626,1382],{"class":499},[235,17628,1517],{"class":499},[235,17630,15969],{"class":245},[235,17632,1517],{"class":499},[235,17634,13706],{"class":1375},[235,17636,1382],{"class":499},[235,17638,13711],{"class":499},[235,17640,1487],{"class":499},[235,17642,17643,17645,17647,17649,17651,17653,17655,17657,17659,17661,17663,17665,17667,17669,17671,17673,17675],{"class":237,"line":590},[235,17644,9208],{"class":499},[235,17646,13693],{"class":495},[235,17648,9310],{"class":1375},[235,17650,1382],{"class":499},[235,17652,1517],{"class":499},[235,17654,17404],{"class":245},[235,17656,1517],{"class":499},[235,17658,17143],{"class":1375},[235,17660,1382],{"class":499},[235,17662,1517],{"class":499},[235,17664,17415],{"class":245},[235,17666,1517],{"class":499},[235,17668,13706],{"class":1375},[235,17670,1382],{"class":499},[235,17672,13711],{"class":499},[235,17674,1524],{"class":499},[235,17676,17304],{"class":3119},[235,17678,17679,17681,17683,17685,17687,17689,17691,17693,17695,17697,17699,17701,17703],{"class":237,"line":604},[235,17680,9208],{"class":499},[235,17682,13693],{"class":495},[235,17684,9310],{"class":1375},[235,17686,1382],{"class":499},[235,17688,1517],{"class":499},[235,17690,17174],{"class":245},[235,17692,1517],{"class":499},[235,17694,13706],{"class":1375},[235,17696,1382],{"class":499},[235,17698,1517],{"class":499},[235,17700,17185],{"class":245},[235,17702,1517],{"class":499},[235,17704,1487],{"class":499},[235,17706,17707,17709,17711],{"class":237,"line":612},[235,17708,9278],{"class":499},[235,17710,17110],{"class":495},[235,17712,1487],{"class":499},[235,17714,17715,17717,17719],{"class":237,"line":623},[235,17716,1539],{"class":499},[235,17718,4677],{"class":495},[235,17720,1487],{"class":499},[235,17722,17723],{"class":237,"line":634},[235,17724,263],{"emptyLinePlaceholder":262},[235,17726,17727,17729,17731],{"class":237,"line":641},[235,17728,1492],{"class":499},[235,17730,1558],{"class":495},[235,17732,1487],{"class":499},[235,17734,17735,17738,17741,17743,17746,17748],{"class":237,"line":653},[235,17736,17737],{"class":1375},"        function",[235,17739,17740],{"class":252}," checkCaptcha",[235,17742,1705],{"class":499},[235,17744,17745],{"class":4527},"e",[235,17747,1715],{"class":499},[235,17749,1276],{"class":499},[235,17751,17752,17755,17757,17760,17762],{"class":237,"line":661},[235,17753,17754],{"class":519},"            e",[235,17756,1694],{"class":499},[235,17758,17759],{"class":252},"preventDefault",[235,17761,2224],{"class":495},[235,17763,1348],{"class":499},[235,17765,17766,17769,17771,17774,17776,17779,17781],{"class":237,"line":670},[235,17767,17768],{"class":519},"            grecaptcha",[235,17770,1694],{"class":499},[235,17772,17773],{"class":252},"ready",[235,17775,1705],{"class":495},[235,17777,17778],{"class":1375},"function",[235,17780,2224],{"class":499},[235,17782,1276],{"class":499},[235,17784,17785,17788,17790,17793,17795,17797,17799,17801,17803,17805,17808,17810,17812,17814,17816,17818,17820,17822,17824,17826,17828,17830,17833,17835],{"class":237,"line":678},[235,17786,17787],{"class":519},"                grecaptcha",[235,17789,1694],{"class":499},[235,17791,17792],{"class":252},"execute",[235,17794,1705],{"class":495},[235,17796,1345],{"class":499},[235,17798,17487],{"class":245},[235,17800,1345],{"class":499},[235,17802,1404],{"class":499},[235,17804,6813],{"class":499},[235,17806,17807],{"class":495},"action",[235,17809,500],{"class":499},[235,17811,503],{"class":499},[235,17813,17174],{"class":245},[235,17815,1345],{"class":499},[235,17817,1950],{"class":499},[235,17819,1715],{"class":495},[235,17821,1694],{"class":499},[235,17823,13367],{"class":252},[235,17825,1705],{"class":495},[235,17827,17778],{"class":1375},[235,17829,1705],{"class":499},[235,17831,17832],{"class":4527},"token",[235,17834,1715],{"class":499},[235,17836,1276],{"class":499},[235,17838,17839,17842,17844,17846,17848,17850,17852,17854,17856,17858,17861,17863,17865],{"class":237,"line":686},[235,17840,17841],{"class":519},"                    document",[235,17843,1694],{"class":499},[235,17845,9481],{"class":252},[235,17847,1705],{"class":495},[235,17849,1517],{"class":499},[235,17851,17415],{"class":245},[235,17853,1517],{"class":499},[235,17855,1715],{"class":495},[235,17857,1694],{"class":499},[235,17859,17860],{"class":519},"value",[235,17862,1382],{"class":499},[235,17864,17832],{"class":519},[235,17866,1348],{"class":499},[235,17868,17869,17871,17873,17875,17877,17879,17881,17883,17885,17887,17889,17891],{"class":237,"line":694},[235,17870,17841],{"class":519},[235,17872,1694],{"class":499},[235,17874,9481],{"class":252},[235,17876,1705],{"class":495},[235,17878,1517],{"class":499},[235,17880,17349],{"class":245},[235,17882,1517],{"class":499},[235,17884,1715],{"class":495},[235,17886,1694],{"class":499},[235,17888,17174],{"class":252},[235,17890,2224],{"class":495},[235,17892,1348],{"class":499},[235,17894,17895,17898,17900],{"class":237,"line":702},[235,17896,17897],{"class":499},"                }",[235,17899,1715],{"class":495},[235,17901,1348],{"class":499},[235,17903,17904,17907,17909],{"class":237,"line":712},[235,17905,17906],{"class":499},"            }",[235,17908,1715],{"class":495},[235,17910,1348],{"class":499},[235,17912,17913],{"class":237,"line":723},[235,17914,4086],{"class":499},[235,17916,17917,17920,17922,17924,17926,17928,17930,17932,17934,17936,17938,17940,17942,17944,17946,17948,17951],{"class":237,"line":730},[235,17918,17919],{"class":519},"        document",[235,17921,1694],{"class":499},[235,17923,9481],{"class":252},[235,17925,1705],{"class":519},[235,17927,1517],{"class":499},[235,17929,17349],{"class":245},[235,17931,1517],{"class":499},[235,17933,1715],{"class":519},[235,17935,1694],{"class":499},[235,17937,9675],{"class":252},[235,17939,1705],{"class":519},[235,17941,1345],{"class":499},[235,17943,17174],{"class":245},[235,17945,1345],{"class":499},[235,17947,1404],{"class":499},[235,17949,17950],{"class":519}," checkCaptcha)",[235,17952,1348],{"class":499},[235,17954,17955,17957,17959],{"class":237,"line":741},[235,17956,9278],{"class":499},[235,17958,1558],{"class":495},[235,17960,1487],{"class":499},[235,17962,17963,17965,17967],{"class":237,"line":752},[235,17964,1530],{"class":499},[235,17966,3947],{"class":495},[235,17968,1487],{"class":499},[13,17970,17971,17972,17975,17976,17979],{},"フォームの送信ボタンが押された時（submitイベント発火時）に",[39,17973,17974],{},"checkCaptcha","の関数が実行される様に設定します。",[39,17977,17978],{},"e.preventDefault();","を使用してそのままフォームが送信されない様にします。",[13,17981,17982,17983,17986,17987,17990,17991,17994,17995,17997,17998,18001],{},"reCAPTCHAのスクリプトによって",[39,17984,17985],{},"grecaptcha","というオブジェクトが使用できる様になり、その中の",[39,17988,17989],{},"grecaptcha.execute()","にてAPIを実行します。第一引数にフロントのキー、第二引数にアクションを入力します。Promiseなので",[39,17992,17993],{},"then(token)","内のコールバックでトークンを",[39,17996,17491],{},"に突っ込みます。そしてフォームを",[39,17999,18000],{},"submit()","にて送信します。",[13,18003,18004],{},"これでフロントの実装は完了です。フロントでの動きをみてreCAPTCHAはbotかどうかを判断し、この送信を一意なトークンで保存しているのです。トークンはバックエンドでの検証で利用します。",[74,18006,18007],{"id":18007},"バックエンドの実装",[13,18009,18010],{},"それではバックエンドの実装をすすめます。Laravelのコントローラーでの記述を想定しています。バリデーションなどは各自設定してください。",[13,18012,18013],{},"バックエンドで行うことは",[17,18015,18016,18019,18022],{},[20,18017,18018],{},"フロントからきたトークンをreCAPTCHAのAPIに送信",[20,18020,18021],{},"reCAPTCHAの結果を取得する",[20,18023,18024],{},"結果（スコア）を用いてbotかの判断をする",[13,18026,18027],{},"以上となります。コードは以下の通りです。",[226,18029,18031],{"className":1026,"code":18030,"language":1029,"meta":231,"style":231},"class Controller extends BaseController\n{\n    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;\n\n    public function checkRecaptcha(Request $request){\n        try {\n            $client = new \\GuzzleHttp\\Client([\n                'headers' => [\n                    'Content-Type' => 'application\u002Fjson',\n                ],\n            ]);\n    \n            $promise = $client->postAsync('https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fapi\u002Fsiteverify',\n            [\n                'form_params' =>[\n                    'secret'=>env('RECAPTCHA_SERVER_KEY'),\n                    'response'=>$request->recaptcha\n                ]\n            ]);\n    \n            $res = Promise\\Utils::settle($promise)->wait();\n            $isFulfilled = isset($res[0]['value']);\n            if(!$isFulfilled) throw new \\Exception('RECAPTCHA SERVER returns error');\n    \n            $result = json_decode($res[0]['value']->getBody()->getContents(),true);\n            \n            if(isset($result['error-codes'])){\n                if($result['error-codes'][0] === 'timeout-or-duplicate') return false;\n                throw new \\Exception('RECAPTCHA SERVER returns error:'.$result['error-codes'][0]);\n            }\n\n            return $result['score'] > 0.5 && $result['success'];\n        }catch (\\Exception $e) {\n            report($e);\n            return false;\n        }\n    }\n}\n",[39,18032,18033,18038,18042,18047,18051,18056,18061,18066,18071,18076,18081,18086,18090,18095,18100,18105,18110,18115,18119,18123,18127,18132,18137,18142,18146,18151,18155,18160,18165,18170,18174,18178,18183,18188,18193,18198,18202,18206],{"__ignoreMap":231},[235,18034,18035],{"class":237,"line":238},[235,18036,18037],{},"class Controller extends BaseController\n",[235,18039,18040],{"class":237,"line":249},[235,18041,1976],{},[235,18043,18044],{"class":237,"line":259},[235,18045,18046],{},"    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;\n",[235,18048,18049],{"class":237,"line":266},[235,18050,263],{"emptyLinePlaceholder":262},[235,18052,18053],{"class":237,"line":275},[235,18054,18055],{},"    public function checkRecaptcha(Request $request){\n",[235,18057,18058],{"class":237,"line":283},[235,18059,18060],{},"        try {\n",[235,18062,18063],{"class":237,"line":291},[235,18064,18065],{},"            $client = new \\GuzzleHttp\\Client([\n",[235,18067,18068],{"class":237,"line":298},[235,18069,18070],{},"                'headers' => [\n",[235,18072,18073],{"class":237,"line":380},[235,18074,18075],{},"                    'Content-Type' => 'application\u002Fjson',\n",[235,18077,18078],{"class":237,"line":465},[235,18079,18080],{},"                ],\n",[235,18082,18083],{"class":237,"line":590},[235,18084,18085],{},"            ]);\n",[235,18087,18088],{"class":237,"line":604},[235,18089,4160],{},[235,18091,18092],{"class":237,"line":612},[235,18093,18094],{},"            $promise = $client->postAsync('https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fapi\u002Fsiteverify',\n",[235,18096,18097],{"class":237,"line":623},[235,18098,18099],{},"            [\n",[235,18101,18102],{"class":237,"line":634},[235,18103,18104],{},"                'form_params' =>[\n",[235,18106,18107],{"class":237,"line":641},[235,18108,18109],{},"                    'secret'=>env('RECAPTCHA_SERVER_KEY'),\n",[235,18111,18112],{"class":237,"line":653},[235,18113,18114],{},"                    'response'=>$request->recaptcha\n",[235,18116,18117],{"class":237,"line":661},[235,18118,14145],{},[235,18120,18121],{"class":237,"line":670},[235,18122,18085],{},[235,18124,18125],{"class":237,"line":678},[235,18126,4160],{},[235,18128,18129],{"class":237,"line":686},[235,18130,18131],{},"            $res = Promise\\Utils::settle($promise)->wait();\n",[235,18133,18134],{"class":237,"line":694},[235,18135,18136],{},"            $isFulfilled = isset($res[0]['value']);\n",[235,18138,18139],{"class":237,"line":702},[235,18140,18141],{},"            if(!$isFulfilled) throw new \\Exception('RECAPTCHA SERVER returns error');\n",[235,18143,18144],{"class":237,"line":712},[235,18145,4160],{},[235,18147,18148],{"class":237,"line":723},[235,18149,18150],{},"            $result = json_decode($res[0]['value']->getBody()->getContents(),true);\n",[235,18152,18153],{"class":237,"line":730},[235,18154,5489],{},[235,18156,18157],{"class":237,"line":741},[235,18158,18159],{},"            if(isset($result['error-codes'])){\n",[235,18161,18162],{"class":237,"line":752},[235,18163,18164],{},"                if($result['error-codes'][0] === 'timeout-or-duplicate') return false;\n",[235,18166,18167],{"class":237,"line":763},[235,18168,18169],{},"                throw new \\Exception('RECAPTCHA SERVER returns error:'.$result['error-codes'][0]);\n",[235,18171,18172],{"class":237,"line":774},[235,18173,5812],{},[235,18175,18176],{"class":237,"line":785},[235,18177,263],{"emptyLinePlaceholder":262},[235,18179,18180],{"class":237,"line":794},[235,18181,18182],{},"            return $result['score'] > 0.5 && $result['success'];\n",[235,18184,18185],{"class":237,"line":806},[235,18186,18187],{},"        }catch (\\Exception $e) {\n",[235,18189,18190],{"class":237,"line":815},[235,18191,18192],{},"            report($e);\n",[235,18194,18195],{"class":237,"line":823},[235,18196,18197],{},"            return false;\n",[235,18199,18200],{"class":237,"line":833},[235,18201,4086],{},[235,18203,18204],{"class":237,"line":3537},[235,18205,2181],{},[235,18207,18208],{"class":237,"line":3542},[235,18209,1317],{},[13,18211,18212,18213,18216,18217,18220],{},"recaptchaとのAPI通信には",[39,18214,18215],{},"Guzzle","を使用していますが、とにかくAPI通信ができれば大丈夫です。APIは",[39,18218,18219],{},"https:\u002F\u002Fwww.google.com\u002Frecaptcha\u002Fapi\u002Fsiteverify","にPOSTを送信します。POSTには以下の値が必要です、",[226,18222,18224],{"className":1026,"code":18223,"language":1029,"meta":231,"style":231},"'form_params' =>[\n    'secret'=>env('RECAPTCHA_SERVER_KEY'),\n    'response'=>$request->recaptcha\n]\n",[39,18225,18226,18231,18236,18241],{"__ignoreMap":231},[235,18227,18228],{"class":237,"line":238},[235,18229,18230],{},"'form_params' =>[\n",[235,18232,18233],{"class":237,"line":249},[235,18234,18235],{},"    'secret'=>env('RECAPTCHA_SERVER_KEY'),\n",[235,18237,18238],{"class":237,"line":259},[235,18239,18240],{},"    'response'=>$request->recaptcha\n",[235,18242,18243],{"class":237,"line":266},[235,18244,1444],{},[13,18246,18247,18250,18251,1216,18254,18256,18257,18260],{},[39,18248,18249],{},"env('RECAPTCHA_SERVER_KEY')","はバックエンドで使用するrecaptchaキーです。",[39,18252,18253],{},"$request->recaptcha",[39,18255,17491],{},"で挿入されたフロントで取得したrecaptchaのトークンです。このトークンとキーを合わせて、 ",[3700,18258,18259],{},"保護対象のサーバーであり、検証を行うフォーム送信","　を判別しています。",[13,18262,18263],{},"通信が成功すると以下の様なレスポンスが戻ります。",[226,18265,18267],{"className":1026,"code":18266,"language":1029,"meta":231,"style":231},"[\n  \"success\"=> true, \n  \"score\"=> 0.8,\n  \"action\"=> string,\n  \"challenge_ts\"=> timestamp,\n  \"hostname\"=> string,\n]\n",[39,18268,18269,18273,18278,18283,18288,18293,18298],{"__ignoreMap":231},[235,18270,18271],{"class":237,"line":238},[235,18272,12342],{},[235,18274,18275],{"class":237,"line":249},[235,18276,18277],{},"  \"success\"=> true, \n",[235,18279,18280],{"class":237,"line":259},[235,18281,18282],{},"  \"score\"=> 0.8,\n",[235,18284,18285],{"class":237,"line":266},[235,18286,18287],{},"  \"action\"=> string,\n",[235,18289,18290],{"class":237,"line":275},[235,18291,18292],{},"  \"challenge_ts\"=> timestamp,\n",[235,18294,18295],{"class":237,"line":283},[235,18296,18297],{},"  \"hostname\"=> string,\n",[235,18299,18300],{"class":237,"line":291},[235,18301,1444],{},[13,18303,18304,18305,18308,18309,18312],{},"一番重要なのは",[39,18306,18307],{},"\"score\"=> 0.8","です。このスコアは入力したリクエストがbotか人間かのスコアを示しており、1に近いほど人間が入力しています。逆に0.1あたりはbotの入力です。どこまで厳しくするかはお任せしますが、私は0.5以上であれば人間のリクエストであるとしています。",[39,18310,18311],{},"return $result['score'] > 0.5"," としてfalseであればリクエストを拒否したり、エラーを返す様にします。フォーム系で汎用的に使用できる様に私はサービスプロバイダにしています。",[81,18314,18315],{"id":18315},"エラー処理",[13,18317,18318],{},"エラーの場合は以下の様なレスポンスがきます。（例です）",[226,18320,18322],{"className":1026,"code":18321,"language":1029,"meta":231,"style":231},"[\n  \"success\"=> false, \n  \"action\"=> string,\n  \"challenge_ts\"=> timestamp,\n  \"hostname\"=> string,\n  \"error-codes\": [\n      0=>'timeout-or-duplicate'\n  ] \n]\n",[39,18323,18324,18328,18333,18337,18341,18345,18350,18355,18360],{"__ignoreMap":231},[235,18325,18326],{"class":237,"line":238},[235,18327,12342],{},[235,18329,18330],{"class":237,"line":249},[235,18331,18332],{},"  \"success\"=> false, \n",[235,18334,18335],{"class":237,"line":259},[235,18336,18287],{},[235,18338,18339],{"class":237,"line":266},[235,18340,18292],{},[235,18342,18343],{"class":237,"line":275},[235,18344,18297],{},[235,18346,18347],{"class":237,"line":283},[235,18348,18349],{},"  \"error-codes\": [\n",[235,18351,18352],{"class":237,"line":291},[235,18353,18354],{},"      0=>'timeout-or-duplicate'\n",[235,18356,18357],{"class":237,"line":298},[235,18358,18359],{},"  ] \n",[235,18361,18362],{"class":237,"line":380},[235,18363,1444],{},[13,18365,18366,18367,18370],{},"このエラーはAPIの通信が失敗したり、必要なパラメーターが不足していたりなどのエラーです。 ",[3700,18368,18369],{},"リクエストがBotである"," という意味ではないので注意。Botかの判定はあくまで成功時に取得するscoreで判定します。",[81,18372,18373],{"id":18373},"エラーの説明",[13,18375,18376,18379,18381],{},[3700,18377,18378],{},"missing-input-secret",[39,18380,18249],{},"のようなサーバー側のrecaptchaのキーを忘れている。",[226,18383,18385],{"className":1026,"code":18384,"language":1029,"meta":231,"style":231},"'form_params' =>[\n    'secret'=>env('RECAPTCHA_SERVER_KEY'), \u002F\u002F このへん\n    'response'=>$request->recaptcha\n]\n",[39,18386,18387,18391,18399,18403],{"__ignoreMap":231},[235,18388,18389],{"class":237,"line":238},[235,18390,18230],{},[235,18392,18393,18396],{"class":237,"line":249},[235,18394,18395],{},"    'secret'=>env('RECAPTCHA_SERVER_KEY'),",[235,18397,18398],{}," \u002F\u002F このへん\n",[235,18400,18401],{"class":237,"line":259},[235,18402,18240],{},[235,18404,18405],{"class":237,"line":266},[235,18406,1444],{},[13,18408,18409,18412,18414],{},[3700,18410,18411],{},"invalid-input-secret",[39,18413,18249],{},"が不正。間違っているキーを使用している。キーが正しいか、保護対象のドメインとして登録しているかを確認。",[13,18416,18417,18420,18423],{},[3700,18418,18419],{},"missing-input-response",[39,18421,18422],{},"'response'=>$request->recaptcha","を忘れている、空文字。",[13,18425,18426,18429,18431],{},[3700,18427,18428],{},"invalid-input-response",[39,18430,18422],{},"の値が不正。型などを確認。",[13,18433,18434,18437],{},[3700,18435,18436],{},"bad-request","\nPOSTで送っているかを確認。",[13,18439,18440,18443,18445],{},[3700,18441,18442],{},"timeout-or-duplicate",[39,18444,18422],{},"の値を二回送っているか、フロントのトークンが２分以上経過した。",[13,18447,18448],{},"フロントで取得したトークンはバックエンドでのこの検証を行うともう一度利用することができません。またこのトークンは",[226,18450,18452],{"className":3990,"code":18451,"language":3992,"meta":231,"style":231},"grecaptcha.execute('YOUR_FRONT_KEY', {action: 'submit'}).then(function(token) {\n    document.getElementById(\"recaptcha\").value=token;\n    document.getElementById(\"test-form\").submit();\n});\n",[39,18453,18454,18504,18533,18559],{"__ignoreMap":231},[235,18455,18456,18458,18460,18462,18464,18466,18468,18470,18472,18474,18476,18478,18480,18482,18484,18486,18488,18490,18492,18494,18496,18498,18500,18502],{"class":237,"line":238},[235,18457,17985],{"class":519},[235,18459,1694],{"class":499},[235,18461,17792],{"class":252},[235,18463,1705],{"class":519},[235,18465,1345],{"class":499},[235,18467,17487],{"class":245},[235,18469,1345],{"class":499},[235,18471,1404],{"class":499},[235,18473,6813],{"class":499},[235,18475,17807],{"class":495},[235,18477,500],{"class":499},[235,18479,503],{"class":499},[235,18481,17174],{"class":245},[235,18483,1345],{"class":499},[235,18485,1950],{"class":499},[235,18487,1715],{"class":519},[235,18489,1694],{"class":499},[235,18491,13367],{"class":252},[235,18493,1705],{"class":519},[235,18495,17778],{"class":1375},[235,18497,1705],{"class":499},[235,18499,17832],{"class":4527},[235,18501,1715],{"class":499},[235,18503,1276],{"class":499},[235,18505,18506,18509,18511,18513,18515,18517,18519,18521,18523,18525,18527,18529,18531],{"class":237,"line":249},[235,18507,18508],{"class":519},"    document",[235,18510,1694],{"class":499},[235,18512,9481],{"class":252},[235,18514,1705],{"class":495},[235,18516,1517],{"class":499},[235,18518,17415],{"class":245},[235,18520,1517],{"class":499},[235,18522,1715],{"class":495},[235,18524,1694],{"class":499},[235,18526,17860],{"class":519},[235,18528,1382],{"class":499},[235,18530,17832],{"class":519},[235,18532,1348],{"class":499},[235,18534,18535,18537,18539,18541,18543,18545,18547,18549,18551,18553,18555,18557],{"class":237,"line":259},[235,18536,18508],{"class":519},[235,18538,1694],{"class":499},[235,18540,9481],{"class":252},[235,18542,1705],{"class":495},[235,18544,1517],{"class":499},[235,18546,17349],{"class":245},[235,18548,1517],{"class":499},[235,18550,1715],{"class":495},[235,18552,1694],{"class":499},[235,18554,17174],{"class":252},[235,18556,2224],{"class":495},[235,18558,1348],{"class":499},[235,18560,18561,18563,18565],{"class":237,"line":266},[235,18562,1950],{"class":499},[235,18564,1715],{"class":519},[235,18566,1348],{"class":499},[13,18568,18569],{},"の実行から２分以内で利用する必要があります。そのためページがリロードされた瞬間ときに実行していると、フォーム入力中に時間切れになったります。そのためsubmit時に実行することをお勧めします。",[74,18571,18572],{"id":18572},"実装まとめ",[13,18574,18575],{},"以上がrecaptchaの実装方法です。recaptchaはあくまでBotかどうかの判断のみをしているので、実際にリクエストを通すかはアプリケーション側の仕事です。フロントとバックでの実装が少し面倒ですが、recaptchaの機能を自前で実装しようとするとそこそこ、面倒なのと実績のあるGoogle様に検証してもらうのも結構安心です。",[13,18577,18578],{},"バックエンドはLaravelを想定しますが、他のフレームワークや言語でもやることは特に変わりません。上手くご自身の環境に置き換えてください。",[2399,18580,18581],{},"html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}",{"title":231,"searchDepth":259,"depth":259,"links":18583},[18584,18585,18586,18587,18591,18595],{"id":16988,"depth":249,"text":16989},{"id":16995,"depth":249,"text":16995},{"id":17004,"depth":249,"text":17005},{"id":17044,"depth":249,"text":17044,"children":18588},[18589,18590],{"id":17239,"depth":259,"text":17240},{"id":17495,"depth":259,"text":17495},{"id":18007,"depth":249,"text":18007,"children":18592},[18593,18594],{"id":18315,"depth":259,"text":18315},{"id":18373,"depth":259,"text":18373},{"id":18572,"depth":249,"text":18572},[2427],"2021-05-21","reCAPTCHAのbot検証をフロントエンド とLaravelでのバックエンドの実装を行います。",{},"\u002Farticles\u002Fimplement-recaptcha",{"title":16971,"description":18598},"articles\u002Fimplement-recaptcha",[1029,1262,971,18604],"security","_mix\u002Flaravel-recaptcha.jpg","AYarFTQUZE-KIUOU5A3co7uCUDW9hqT091VEnFYUN6Q",{"id":18608,"title":18609,"body":18610,"category":20364,"createdAt":20365,"description":20366,"extension":2430,"index":266,"meta":20367,"navigation":262,"path":20368,"publish":262,"seo":20369,"series":20370,"seriesTitle":20371,"stem":20372,"tag":20373,"thumbnail":20374,"updatedAt":2439,"__hash__":20375},"series\u002Fseries\u002Fnuxt-content-blog-4.md","Nuxt Content × SSG で作る静的ブログ。４：カテゴリーとタグ機能",{"type":10,"value":18611,"toc":20355},[18612,18624,18627,18630,18633,18636,18640,18643,18755,18764,18771,18775,18782,19440,19446,19813,19820,19867,19870,19874,19877,19884,19890,19896,19903,19907,19913,20295,20309,20312,20315,20328,20332,20335,20349,20352],[13,18613,18614,18615,18619,18620,18623],{},"こんにちはjunです。",[197,18616,18618],{"href":18617},"\u002Fseries\u002Fnuxt-content-blog\u002F3","前回の記事","は詳細ページの実装と静的書き出しを行いました。今回の記事では ",[3700,18621,18622],{},"カテゴリーとタグ機能","　について解説します。",[74,18625,18626],{"id":18626},"カテゴリーとタグについて",[13,18628,18629],{},"まず最初にカテゴリーとタグ機能について念のため定義しておきます。基本的にはwordpressのものと概念は似ています。カテゴリーは基本的に記事に一つだけ設定して大まかな分類を行います。タグは記事に対して複数個設定できます。",[13,18631,18632],{},"機能としては上記の通りですが、記事がどんなコンテンツであるか整理されてリスト化されることでサイト訪問者がコンテンツを探しやすくなります。実際私のサイトもわかりやすくありませんか笑？",[13,18634,18635],{},"そのためブログを作るのならば、このカテゴリーとタグの機能はかなり重要です。それでは早速解説します。",[74,18637,18639],{"id":18638},"各記事にカテゴリータグを設定する","各記事にカテゴリー・タグを設定する",[13,18641,18642],{},"Nuxt Contentはマークダウンで原稿を作成します。マークダウン上部には以下のような記事のメタデータを記述します。",[226,18644,18648],{"className":18645,"code":18646,"language":18647,"meta":231,"style":231},"language-yml shiki shiki-themes material-theme-ocean","---\ntitle: Nuxt Content × SSG で作る静的ブログ。４：カテゴリーとタグ機能\ndescription: Nuxt Content × SSG で作る静的ブログ。カテゴリーとタグ機能\ncategory: [devstack]\ntag: [js,nuxt]\nseries: nuxt-content-blog\nseriesTitle: Nuxt Content × SSG で作る静的ブログ。\nindex: 4\npublish: true\nthumbnail:  _mix\u002Flogo-dark.jpg\n---\n","yml",[39,18649,18650,18655,18664,18673,18685,18702,18712,18722,18731,18741,18751],{"__ignoreMap":231},[235,18651,18652],{"class":237,"line":238},[235,18653,18654],{"class":241},"---\n",[235,18656,18657,18659,18661],{"class":237,"line":249},[235,18658,9125],{"class":495},[235,18660,500],{"class":499},[235,18662,18663],{"class":245}," Nuxt Content × SSG で作る静的ブログ。４：カテゴリーとタグ機能\n",[235,18665,18666,18668,18670],{"class":237,"line":259},[235,18667,12404],{"class":495},[235,18669,500],{"class":499},[235,18671,18672],{"class":245}," Nuxt Content × SSG で作る静的ブログ。カテゴリーとタグ機能\n",[235,18674,18675,18677,18679,18681,18683],{"class":237,"line":266},[235,18676,12443],{"class":495},[235,18678,500],{"class":499},[235,18680,5192],{"class":499},[235,18682,2427],{"class":245},[235,18684,1444],{"class":499},[235,18686,18687,18689,18691,18693,18695,18697,18700],{"class":237,"line":275},[235,18688,12465],{"class":495},[235,18690,500],{"class":499},[235,18692,5192],{"class":499},[235,18694,1262],{"class":245},[235,18696,1404],{"class":499},[235,18698,18699],{"class":245},"nuxt",[235,18701,1444],{"class":499},[235,18703,18704,18707,18709],{"class":237,"line":283},[235,18705,18706],{"class":495},"series",[235,18708,500],{"class":499},[235,18710,18711],{"class":245}," nuxt-content-blog\n",[235,18713,18714,18717,18719],{"class":237,"line":291},[235,18715,18716],{"class":495},"seriesTitle",[235,18718,500],{"class":499},[235,18720,18721],{"class":245}," Nuxt Content × SSG で作る静的ブログ。\n",[235,18723,18724,18726,18728],{"class":237,"line":298},[235,18725,10472],{"class":495},[235,18727,500],{"class":499},[235,18729,18730],{"class":2836}," 4\n",[235,18732,18733,18736,18738],{"class":237,"line":380},[235,18734,18735],{"class":495},"publish",[235,18737,500],{"class":499},[235,18739,18740],{"class":4702}," true\n",[235,18742,18743,18746,18748],{"class":237,"line":465},[235,18744,18745],{"class":495},"thumbnail",[235,18747,500],{"class":499},[235,18749,18750],{"class":245},"  _mix\u002Flogo-dark.jpg\n",[235,18752,18753],{"class":237,"line":590},[235,18754,18654],{"class":241},[13,18756,18757,18758,13843,18760,18763],{},"ここで設定する値は基本的に自由につけることができます。そしてこの例の",[39,18759,12443],{},[39,18761,18762],{},"tags","に注目してみてください。各記事のカテゴリーとタグはここで定義されています。そして配列形式で設定します。このようにメタデータに配列で設定することで記事のカテゴリー・タグを配列で取得できます。配列なので複数個設定することができます。",[13,18765,18766,18767,18770],{},"この時気をつけたいのが、例えば",[39,18768,18769],{},"[開発スタック,メモ]","と日本語（ラベル）を入力するのでなく、プログラム的なキー・スラグで入力した方が良いです。理由は後述します。",[74,18772,18774],{"id":18773},"カテゴリータグ設定ファイルを作成する","カテゴリー、タグ設定ファイルを作成する",[13,18776,18777,18778,18781],{},"プロジェクトルートに",[39,18779,18780],{},"taxonomy.js","というようなカテゴリー、タグを管理するファイルを作成します。中身は以下のようになっています。",[226,18783,18785],{"className":3990,"code":18784,"filename":18780,"language":3992,"meta":231,"style":231},"module.exports = {\n    category:[\n        {text:'技術スタック',slug:'devstack'},\n        {text:'プログラミング学習',slug:'learning'},\n        {text:'メモ',slug:'ministack'},\n    ],\n    tags:[\n        {text:'HTML',slug:'html'},\n        {text:'CSS',slug:'css'},\n        {text:'Javascript',slug:'js'},\n        {text:'jquery',slug:'jquery'},\n        {text:'Vue.js',slug:'vue'},\n        {text:'Nuxt.js',slug:'nuxt'},\n        {text:'webpack',slug:'webpack'},\n        {text:'PHP',slug:'php'},\n        {text:'Laravel',slug:'laravel'},\n        {text:'Python',slug:'python'},\n        {text:'Django',slug:'django'},\n        {text:'HeadlessCMS',slug:'headlesscms'},\n        {text:'wordpress',slug:'wordpress'},\n        {text:'concrete5',slug:'concrete5'},\n        {text:'ZOOM',slug:'zoom'},\n        {text:'インフラ',slug:'infrastructure'},\n        {text:'ネットワーク',slug:'network'},\n        {text:'Docker',slug:'docker'},\n    ]\n}\n",[39,18786,18787,18795,18804,18835,18865,18894,18900,18909,18938,18967,18996,19024,19052,19081,19109,19138,19166,19195,19224,19254,19283,19312,19342,19372,19402,19432,19436],{"__ignoreMap":231},[235,18788,18789,18791,18793],{"class":237,"line":238},[235,18790,4220],{"class":499},[235,18792,4116],{"class":499},[235,18794,1276],{"class":499},[235,18796,18797,18800,18802],{"class":237,"line":249},[235,18798,18799],{"class":495},"    category",[235,18801,500],{"class":499},[235,18803,12342],{"class":519},[235,18805,18806,18809,18811,18813,18815,18818,18820,18822,18825,18827,18829,18831,18833],{"class":237,"line":259},[235,18807,18808],{"class":499},"        {",[235,18810,934],{"class":495},[235,18812,500],{"class":499},[235,18814,1345],{"class":499},[235,18816,18817],{"class":245},"技術スタック",[235,18819,1345],{"class":499},[235,18821,1404],{"class":499},[235,18823,18824],{"class":495},"slug",[235,18826,500],{"class":499},[235,18828,1345],{"class":499},[235,18830,2427],{"class":245},[235,18832,1345],{"class":499},[235,18834,1414],{"class":499},[235,18836,18837,18839,18841,18843,18845,18848,18850,18852,18854,18856,18858,18861,18863],{"class":237,"line":266},[235,18838,18808],{"class":499},[235,18840,934],{"class":495},[235,18842,500],{"class":499},[235,18844,1345],{"class":499},[235,18846,18847],{"class":245},"プログラミング学習",[235,18849,1345],{"class":499},[235,18851,1404],{"class":499},[235,18853,18824],{"class":495},[235,18855,500],{"class":499},[235,18857,1345],{"class":499},[235,18859,18860],{"class":245},"learning",[235,18862,1345],{"class":499},[235,18864,1414],{"class":499},[235,18866,18867,18869,18871,18873,18875,18878,18880,18882,18884,18886,18888,18890,18892],{"class":237,"line":275},[235,18868,18808],{"class":499},[235,18870,934],{"class":495},[235,18872,500],{"class":499},[235,18874,1345],{"class":499},[235,18876,18877],{"class":245},"メモ",[235,18879,1345],{"class":499},[235,18881,1404],{"class":499},[235,18883,18824],{"class":495},[235,18885,500],{"class":499},[235,18887,1345],{"class":499},[235,18889,12453],{"class":245},[235,18891,1345],{"class":499},[235,18893,1414],{"class":499},[235,18895,18896,18898],{"class":237,"line":283},[235,18897,14580],{"class":519},[235,18899,1984],{"class":499},[235,18901,18902,18905,18907],{"class":237,"line":291},[235,18903,18904],{"class":495},"    tags",[235,18906,500],{"class":499},[235,18908,12342],{"class":519},[235,18910,18911,18913,18915,18917,18919,18922,18924,18926,18928,18930,18932,18934,18936],{"class":237,"line":298},[235,18912,18808],{"class":499},[235,18914,934],{"class":495},[235,18916,500],{"class":499},[235,18918,1345],{"class":499},[235,18920,18921],{"class":245},"HTML",[235,18923,1345],{"class":499},[235,18925,1404],{"class":499},[235,18927,18824],{"class":495},[235,18929,500],{"class":499},[235,18931,1345],{"class":499},[235,18933,3947],{"class":245},[235,18935,1345],{"class":499},[235,18937,1414],{"class":499},[235,18939,18940,18942,18944,18946,18948,18951,18953,18955,18957,18959,18961,18963,18965],{"class":237,"line":380},[235,18941,18808],{"class":499},[235,18943,934],{"class":495},[235,18945,500],{"class":499},[235,18947,1345],{"class":499},[235,18949,18950],{"class":245},"CSS",[235,18952,1345],{"class":499},[235,18954,1404],{"class":499},[235,18956,18824],{"class":495},[235,18958,500],{"class":499},[235,18960,1345],{"class":499},[235,18962,8177],{"class":245},[235,18964,1345],{"class":499},[235,18966,1414],{"class":499},[235,18968,18969,18971,18973,18975,18977,18980,18982,18984,18986,18988,18990,18992,18994],{"class":237,"line":465},[235,18970,18808],{"class":499},[235,18972,934],{"class":495},[235,18974,500],{"class":499},[235,18976,1345],{"class":499},[235,18978,18979],{"class":245},"Javascript",[235,18981,1345],{"class":499},[235,18983,1404],{"class":499},[235,18985,18824],{"class":495},[235,18987,500],{"class":499},[235,18989,1345],{"class":499},[235,18991,1262],{"class":245},[235,18993,1345],{"class":499},[235,18995,1414],{"class":499},[235,18997,18998,19000,19002,19004,19006,19008,19010,19012,19014,19016,19018,19020,19022],{"class":237,"line":590},[235,18999,18808],{"class":499},[235,19001,934],{"class":495},[235,19003,500],{"class":499},[235,19005,1345],{"class":499},[235,19007,15385],{"class":245},[235,19009,1345],{"class":499},[235,19011,1404],{"class":499},[235,19013,18824],{"class":495},[235,19015,500],{"class":499},[235,19017,1345],{"class":499},[235,19019,15385],{"class":245},[235,19021,1345],{"class":499},[235,19023,1414],{"class":499},[235,19025,19026,19028,19030,19032,19034,19036,19038,19040,19042,19044,19046,19048,19050],{"class":237,"line":604},[235,19027,18808],{"class":499},[235,19029,934],{"class":495},[235,19031,500],{"class":499},[235,19033,1345],{"class":499},[235,19035,45],{"class":245},[235,19037,1345],{"class":499},[235,19039,1404],{"class":499},[235,19041,18824],{"class":495},[235,19043,500],{"class":499},[235,19045,1345],{"class":499},[235,19047,1208],{"class":245},[235,19049,1345],{"class":499},[235,19051,1414],{"class":499},[235,19053,19054,19056,19058,19060,19062,19065,19067,19069,19071,19073,19075,19077,19079],{"class":237,"line":612},[235,19055,18808],{"class":499},[235,19057,934],{"class":495},[235,19059,500],{"class":499},[235,19061,1345],{"class":499},[235,19063,19064],{"class":245},"Nuxt.js",[235,19066,1345],{"class":499},[235,19068,1404],{"class":499},[235,19070,18824],{"class":495},[235,19072,500],{"class":499},[235,19074,1345],{"class":499},[235,19076,18699],{"class":245},[235,19078,1345],{"class":499},[235,19080,1414],{"class":499},[235,19082,19083,19085,19087,19089,19091,19093,19095,19097,19099,19101,19103,19105,19107],{"class":237,"line":623},[235,19084,18808],{"class":499},[235,19086,934],{"class":495},[235,19088,500],{"class":499},[235,19090,1345],{"class":499},[235,19092,7957],{"class":245},[235,19094,1345],{"class":499},[235,19096,1404],{"class":499},[235,19098,18824],{"class":495},[235,19100,500],{"class":499},[235,19102,1345],{"class":499},[235,19104,7957],{"class":245},[235,19106,1345],{"class":499},[235,19108,1414],{"class":499},[235,19110,19111,19113,19115,19117,19119,19122,19124,19126,19128,19130,19132,19134,19136],{"class":237,"line":634},[235,19112,18808],{"class":499},[235,19114,934],{"class":495},[235,19116,500],{"class":499},[235,19118,1345],{"class":499},[235,19120,19121],{"class":245},"PHP",[235,19123,1345],{"class":499},[235,19125,1404],{"class":499},[235,19127,18824],{"class":495},[235,19129,500],{"class":499},[235,19131,1345],{"class":499},[235,19133,1029],{"class":245},[235,19135,1345],{"class":499},[235,19137,1414],{"class":499},[235,19139,19140,19142,19144,19146,19148,19150,19152,19154,19156,19158,19160,19162,19164],{"class":237,"line":641},[235,19141,18808],{"class":499},[235,19143,934],{"class":495},[235,19145,500],{"class":499},[235,19147,1345],{"class":499},[235,19149,41],{"class":245},[235,19151,1345],{"class":499},[235,19153,1404],{"class":499},[235,19155,18824],{"class":495},[235,19157,500],{"class":499},[235,19159,1345],{"class":499},[235,19161,971],{"class":245},[235,19163,1345],{"class":499},[235,19165,1414],{"class":499},[235,19167,19168,19170,19172,19174,19176,19179,19181,19183,19185,19187,19189,19191,19193],{"class":237,"line":653},[235,19169,18808],{"class":499},[235,19171,934],{"class":495},[235,19173,500],{"class":499},[235,19175,1345],{"class":499},[235,19177,19178],{"class":245},"Python",[235,19180,1345],{"class":499},[235,19182,1404],{"class":499},[235,19184,18824],{"class":495},[235,19186,500],{"class":499},[235,19188,1345],{"class":499},[235,19190,3360],{"class":245},[235,19192,1345],{"class":499},[235,19194,1414],{"class":499},[235,19196,19197,19199,19201,19203,19205,19208,19210,19212,19214,19216,19218,19220,19222],{"class":237,"line":661},[235,19198,18808],{"class":499},[235,19200,934],{"class":495},[235,19202,500],{"class":499},[235,19204,1345],{"class":499},[235,19206,19207],{"class":245},"Django",[235,19209,1345],{"class":499},[235,19211,1404],{"class":499},[235,19213,18824],{"class":495},[235,19215,500],{"class":499},[235,19217,1345],{"class":499},[235,19219,3877],{"class":245},[235,19221,1345],{"class":499},[235,19223,1414],{"class":499},[235,19225,19226,19228,19230,19232,19234,19237,19239,19241,19243,19245,19247,19250,19252],{"class":237,"line":670},[235,19227,18808],{"class":499},[235,19229,934],{"class":495},[235,19231,500],{"class":499},[235,19233,1345],{"class":499},[235,19235,19236],{"class":245},"HeadlessCMS",[235,19238,1345],{"class":499},[235,19240,1404],{"class":499},[235,19242,18824],{"class":495},[235,19244,500],{"class":499},[235,19246,1345],{"class":499},[235,19248,19249],{"class":245},"headlesscms",[235,19251,1345],{"class":499},[235,19253,1414],{"class":499},[235,19255,19256,19258,19260,19262,19264,19267,19269,19271,19273,19275,19277,19279,19281],{"class":237,"line":678},[235,19257,18808],{"class":499},[235,19259,934],{"class":495},[235,19261,500],{"class":499},[235,19263,1345],{"class":499},[235,19265,19266],{"class":245},"wordpress",[235,19268,1345],{"class":499},[235,19270,1404],{"class":499},[235,19272,18824],{"class":495},[235,19274,500],{"class":499},[235,19276,1345],{"class":499},[235,19278,19266],{"class":245},[235,19280,1345],{"class":499},[235,19282,1414],{"class":499},[235,19284,19285,19287,19289,19291,19293,19296,19298,19300,19302,19304,19306,19308,19310],{"class":237,"line":686},[235,19286,18808],{"class":499},[235,19288,934],{"class":495},[235,19290,500],{"class":499},[235,19292,1345],{"class":499},[235,19294,19295],{"class":245},"concrete5",[235,19297,1345],{"class":499},[235,19299,1404],{"class":499},[235,19301,18824],{"class":495},[235,19303,500],{"class":499},[235,19305,1345],{"class":499},[235,19307,19295],{"class":245},[235,19309,1345],{"class":499},[235,19311,1414],{"class":499},[235,19313,19314,19316,19318,19320,19322,19325,19327,19329,19331,19333,19335,19338,19340],{"class":237,"line":694},[235,19315,18808],{"class":499},[235,19317,934],{"class":495},[235,19319,500],{"class":499},[235,19321,1345],{"class":499},[235,19323,19324],{"class":245},"ZOOM",[235,19326,1345],{"class":499},[235,19328,1404],{"class":499},[235,19330,18824],{"class":495},[235,19332,500],{"class":499},[235,19334,1345],{"class":499},[235,19336,19337],{"class":245},"zoom",[235,19339,1345],{"class":499},[235,19341,1414],{"class":499},[235,19343,19344,19346,19348,19350,19352,19355,19357,19359,19361,19363,19365,19368,19370],{"class":237,"line":702},[235,19345,18808],{"class":499},[235,19347,934],{"class":495},[235,19349,500],{"class":499},[235,19351,1345],{"class":499},[235,19353,19354],{"class":245},"インフラ",[235,19356,1345],{"class":499},[235,19358,1404],{"class":499},[235,19360,18824],{"class":495},[235,19362,500],{"class":499},[235,19364,1345],{"class":499},[235,19366,19367],{"class":245},"infrastructure",[235,19369,1345],{"class":499},[235,19371,1414],{"class":499},[235,19373,19374,19376,19378,19380,19382,19385,19387,19389,19391,19393,19395,19398,19400],{"class":237,"line":712},[235,19375,18808],{"class":499},[235,19377,934],{"class":495},[235,19379,500],{"class":499},[235,19381,1345],{"class":499},[235,19383,19384],{"class":245},"ネットワーク",[235,19386,1345],{"class":499},[235,19388,1404],{"class":499},[235,19390,18824],{"class":495},[235,19392,500],{"class":499},[235,19394,1345],{"class":499},[235,19396,19397],{"class":245},"network",[235,19399,1345],{"class":499},[235,19401,1414],{"class":499},[235,19403,19404,19406,19408,19410,19412,19415,19417,19419,19421,19423,19425,19428,19430],{"class":237,"line":723},[235,19405,18808],{"class":499},[235,19407,934],{"class":495},[235,19409,500],{"class":499},[235,19411,1345],{"class":499},[235,19413,19414],{"class":245},"Docker",[235,19416,1345],{"class":499},[235,19418,1404],{"class":499},[235,19420,18824],{"class":495},[235,19422,500],{"class":499},[235,19424,1345],{"class":499},[235,19426,19427],{"class":245},"docker",[235,19429,1345],{"class":499},[235,19431,1414],{"class":499},[235,19433,19434],{"class":237,"line":730},[235,19435,7627],{"class":519},[235,19437,19438],{"class":237,"line":741},[235,19439,1317],{"class":499},[13,19441,19442,19445],{},[39,19443,19444],{},"module export"," としているのは静的書き出しの際にこのファイルを使用するからです。そしてNuxtで制御しやすいようにStoreに入れておきます。このように管理する時、キー（スラグ）とラベル（カテゴリ名）を分けてオブジェクトにしておいた方が良いです。キーを使用することで重複を避けたり、そのままURLの一部として使用することも可能です。",[226,19447,19450],{"className":3990,"code":19448,"filename":19449,"language":3992,"meta":231,"style":231},"import taxonomy from '..\u002Ftaxonomy';\nexport const state = () => ({\n    category:[\n        ...taxonomy.category\n    ],\n    tags:[\n        ...taxonomy.tags\n    ]\n  })\n\nexport const getters ={\n    getTagTextBySlug(state){\n        return (slug)=>{\n            const idx = state.tags.findIndex(tag=>{\n                return tag.slug === slug;\n            })\n            return (idx > -1)?state.tags[idx].text:undefined;\n        }\n    },\n    getCategoryTextBySlug(state){\n        return (slug)=>{\n            const idx = state.category.findIndex(tag=>{\n                return tag.slug === slug;\n            })\n            return (idx > -1)?state.category[idx].text:undefined;\n        }\n    }\n}\n","store\u002Findex.js",[39,19451,19452,19470,19490,19498,19511,19517,19525,19536,19540,19546,19550,19562,19575,19590,19619,19639,19645,19684,19688,19692,19703,19717,19743,19759,19765,19801,19805,19809],{"__ignoreMap":231},[235,19453,19454,19456,19459,19461,19463,19466,19468],{"class":237,"line":238},[235,19455,1331],{"class":1269},[235,19457,19458],{"class":519}," taxonomy ",[235,19460,1337],{"class":1269},[235,19462,503],{"class":499},[235,19464,19465],{"class":245},"..\u002Ftaxonomy",[235,19467,1345],{"class":499},[235,19469,1348],{"class":499},[235,19471,19472,19474,19477,19480,19482,19484,19486,19488],{"class":237,"line":249},[235,19473,1270],{"class":1269},[235,19475,19476],{"class":1375}," const",[235,19478,19479],{"class":519}," state ",[235,19481,1382],{"class":499},[235,19483,9731],{"class":499},[235,19485,4533],{"class":1375},[235,19487,10342],{"class":519},[235,19489,1976],{"class":499},[235,19491,19492,19494,19496],{"class":237,"line":259},[235,19493,18799],{"class":495},[235,19495,500],{"class":499},[235,19497,12342],{"class":519},[235,19499,19500,19503,19506,19508],{"class":237,"line":266},[235,19501,19502],{"class":499},"        ...",[235,19504,19505],{"class":519},"taxonomy",[235,19507,1694],{"class":499},[235,19509,19510],{"class":519},"category\n",[235,19512,19513,19515],{"class":237,"line":275},[235,19514,14580],{"class":519},[235,19516,1984],{"class":499},[235,19518,19519,19521,19523],{"class":237,"line":283},[235,19520,18904],{"class":495},[235,19522,500],{"class":499},[235,19524,12342],{"class":519},[235,19526,19527,19529,19531,19533],{"class":237,"line":291},[235,19528,19502],{"class":499},[235,19530,19505],{"class":519},[235,19532,1694],{"class":499},[235,19534,19535],{"class":519},"tags\n",[235,19537,19538],{"class":237,"line":298},[235,19539,7627],{"class":519},[235,19541,19542,19544],{"class":237,"line":380},[235,19543,15996],{"class":499},[235,19545,1953],{"class":519},[235,19547,19548],{"class":237,"line":465},[235,19549,263],{"emptyLinePlaceholder":262},[235,19551,19552,19554,19556,19559],{"class":237,"line":590},[235,19553,1270],{"class":1269},[235,19555,19476],{"class":1375},[235,19557,19558],{"class":519}," getters ",[235,19560,19561],{"class":499},"={\n",[235,19563,19564,19567,19569,19572],{"class":237,"line":604},[235,19565,19566],{"class":495},"    getTagTextBySlug",[235,19568,1705],{"class":499},[235,19570,19571],{"class":4527},"state",[235,19573,19574],{"class":499},"){\n",[235,19576,19577,19580,19582,19584,19586,19588],{"class":237,"line":612},[235,19578,19579],{"class":1269},"        return",[235,19581,10342],{"class":499},[235,19583,18824],{"class":4527},[235,19585,1715],{"class":499},[235,19587,9690],{"class":1375},[235,19589,1976],{"class":499},[235,19591,19592,19595,19598,19600,19603,19605,19607,19609,19611,19613,19615,19617],{"class":237,"line":623},[235,19593,19594],{"class":1375},"            const",[235,19596,19597],{"class":519}," idx",[235,19599,4116],{"class":499},[235,19601,19602],{"class":519}," state",[235,19604,1694],{"class":499},[235,19606,18762],{"class":519},[235,19608,1694],{"class":499},[235,19610,10427],{"class":252},[235,19612,1705],{"class":495},[235,19614,12465],{"class":4527},[235,19616,9690],{"class":1375},[235,19618,1976],{"class":499},[235,19620,19621,19624,19627,19629,19631,19634,19637],{"class":237,"line":634},[235,19622,19623],{"class":1269},"                return",[235,19625,19626],{"class":519}," tag",[235,19628,1694],{"class":499},[235,19630,18824],{"class":519},[235,19632,19633],{"class":499}," ===",[235,19635,19636],{"class":519}," slug",[235,19638,1348],{"class":499},[235,19640,19641,19643],{"class":237,"line":641},[235,19642,17906],{"class":499},[235,19644,1953],{"class":495},[235,19646,19647,19650,19652,19655,19657,19659,19661,19663,19665,19667,19669,19671,19673,19675,19677,19679,19681],{"class":237,"line":653},[235,19648,19649],{"class":1269},"            return",[235,19651,10342],{"class":495},[235,19653,19654],{"class":519},"idx",[235,19656,13744],{"class":499},[235,19658,10576],{"class":499},[235,19660,4576],{"class":2836},[235,19662,1715],{"class":495},[235,19664,7153],{"class":499},[235,19666,19571],{"class":519},[235,19668,1694],{"class":499},[235,19670,18762],{"class":519},[235,19672,7317],{"class":495},[235,19674,19654],{"class":519},[235,19676,4585],{"class":495},[235,19678,1694],{"class":499},[235,19680,934],{"class":519},[235,19682,19683],{"class":499},":undefined;\n",[235,19685,19686],{"class":237,"line":661},[235,19687,4086],{"class":499},[235,19689,19690],{"class":237,"line":670},[235,19691,4091],{"class":499},[235,19693,19694,19697,19699,19701],{"class":237,"line":678},[235,19695,19696],{"class":495},"    getCategoryTextBySlug",[235,19698,1705],{"class":499},[235,19700,19571],{"class":4527},[235,19702,19574],{"class":499},[235,19704,19705,19707,19709,19711,19713,19715],{"class":237,"line":686},[235,19706,19579],{"class":1269},[235,19708,10342],{"class":499},[235,19710,18824],{"class":4527},[235,19712,1715],{"class":499},[235,19714,9690],{"class":1375},[235,19716,1976],{"class":499},[235,19718,19719,19721,19723,19725,19727,19729,19731,19733,19735,19737,19739,19741],{"class":237,"line":694},[235,19720,19594],{"class":1375},[235,19722,19597],{"class":519},[235,19724,4116],{"class":499},[235,19726,19602],{"class":519},[235,19728,1694],{"class":499},[235,19730,12443],{"class":519},[235,19732,1694],{"class":499},[235,19734,10427],{"class":252},[235,19736,1705],{"class":495},[235,19738,12465],{"class":4527},[235,19740,9690],{"class":1375},[235,19742,1976],{"class":499},[235,19744,19745,19747,19749,19751,19753,19755,19757],{"class":237,"line":702},[235,19746,19623],{"class":1269},[235,19748,19626],{"class":519},[235,19750,1694],{"class":499},[235,19752,18824],{"class":519},[235,19754,19633],{"class":499},[235,19756,19636],{"class":519},[235,19758,1348],{"class":499},[235,19760,19761,19763],{"class":237,"line":712},[235,19762,17906],{"class":499},[235,19764,1953],{"class":495},[235,19766,19767,19769,19771,19773,19775,19777,19779,19781,19783,19785,19787,19789,19791,19793,19795,19797,19799],{"class":237,"line":723},[235,19768,19649],{"class":1269},[235,19770,10342],{"class":495},[235,19772,19654],{"class":519},[235,19774,13744],{"class":499},[235,19776,10576],{"class":499},[235,19778,4576],{"class":2836},[235,19780,1715],{"class":495},[235,19782,7153],{"class":499},[235,19784,19571],{"class":519},[235,19786,1694],{"class":499},[235,19788,12443],{"class":519},[235,19790,7317],{"class":495},[235,19792,19654],{"class":519},[235,19794,4585],{"class":495},[235,19796,1694],{"class":499},[235,19798,934],{"class":519},[235,19800,19683],{"class":499},[235,19802,19803],{"class":237,"line":730},[235,19804,4086],{"class":499},[235,19806,19807],{"class":237,"line":741},[235,19808,2181],{"class":499},[235,19810,19811],{"class":237,"line":752},[235,19812,1317],{"class":499},[13,19814,19815,19816,19819],{},"カテゴリー、タグはサイドメニューにあるようにバッチで表示しています。その時は以下のような",[39,19817,19818],{},"v-for","のコンポーネントで表示しています。",[226,19821,19823],{"className":1472,"code":19822,"language":1208,"meta":231,"style":231},"\u003Cdiv class=\"p-badge-container\">\n    \u003Cnuxt-link class=\"c-tag-badge\" v-for=\"(t,index) in $store.state.category\" :key=\"'tag-'+index\" :to=\"'\u002Ftag\u002F'+t\">\n        \u003Cspan>{{t.text}}\u003C\u002Fspan>\n    \u003C\u002Fnuxt-link>\n\u003C\u002Fdiv>\n",[39,19824,19825,19844,19849,19854,19859],{"__ignoreMap":231},[235,19826,19827,19829,19831,19833,19835,19837,19840,19842],{"class":237,"line":238},[235,19828,1481],{"class":499},[235,19830,1225],{"class":495},[235,19832,8005],{"class":1375},[235,19834,1382],{"class":499},[235,19836,1517],{"class":499},[235,19838,19839],{"class":245},"p-badge-container",[235,19841,1517],{"class":499},[235,19843,1487],{"class":499},[235,19845,19846],{"class":237,"line":249},[235,19847,19848],{"class":519},"    \u003Cnuxt-link class=\"c-tag-badge\" v-for=\"(t,index) in $store.state.category\" :key=\"'tag-'+index\" :to=\"'\u002Ftag\u002F'+t\">\n",[235,19850,19851],{"class":237,"line":259},[235,19852,19853],{"class":519},"        \u003Cspan>{{t.text}}\u003C\u002Fspan>\n",[235,19855,19856],{"class":237,"line":266},[235,19857,19858],{"class":519},"    \u003C\u002Fnuxt-link>\n",[235,19860,19861,19863,19865],{"class":237,"line":275},[235,19862,1530],{"class":499},[235,19864,1225],{"class":495},[235,19866,1487],{"class":499},[13,19868,19869],{},"カテゴリー、タグを管理、使用、設定ができるようになりましたので、次はカテゴリー・タグ一覧を作成していきましょう。",[74,19871,19873],{"id":19872},"カテゴリータグ一覧ページのためのpages構成","カテゴリー、タグ一覧ページのためのpages構成",[13,19875,19876],{},"カテゴリーとタグ一覧ページの構成は互いに同じなので、タグ一覧だけ解説します。",[13,19878,19879,19880,19883],{},"タグ一覧はそのタグのバッチをクリックすると閲覧できるページです。そのタグがついた記事を全て見ることが可能です。そして",[39,19881,19882],{},"\u002Ftag\u002F{tag_key}","というURLでルーティングされています。",[13,19885,19886,19887,13519],{},"そのようなルーティングを行うために以下のように",[39,19888,19889],{},"pages\u002F",[226,19891,19894],{"className":19892,"code":19893,"language":934},[932],"pages\n└── tag\n    └── _slug\n        ├── index.vue\n        └── page\n            └── _id.vue\n",[39,19895,19893],{"__ignoreMap":231},[13,19897,19898,19899,19902],{},"こうすうることで",[39,19900,19901],{},"{tag_key}","という動的ルートに対応できます。またページングのためのページコンポーネントも作成しておきます。",[74,19904,19906],{"id":19905},"特定のタグを持つ投稿のみを取得する","特定のタグを持つ投稿のみを取得する。",[13,19908,1243,19909,19912],{},[39,19910,19911],{},"\u002Ftag\u002F_slug\u002Findex.vue","の中身を見ていきましょう。",[226,19914,19917],{"className":3990,"code":19915,"filename":19916,"language":3992,"meta":231,"style":231},"export default {\n    async asyncData({ store,$content, params }) {\n        const count = await $content({ deep: true }).only('title').where({ tag:{ $contains:params.slug}}).fetch();\n\n        const content = await $content({ deep: true })\n        .only(['title','description','thumbnail','path','category','tag','updatedAt','series','index'])\n        .sortBy('createdAt', 'desc')\n        .where({tag:{ $contains:params.slug}}) \u002F\u002F ここ\n        .skip(0).limit(store.state.indexPerPage)\n        .fetch();\n\n        return {\n`        content,\n        count:count.length`\n        }\n    },\n}\n","pages\u002Ftag\u002F_slug\u002Findex.vue",[39,19918,19919,19927,19956,20041,20045,20072,20156,20183,20214,20248,20258,20262,20268,20275,20283,20287,20291],{"__ignoreMap":231},[235,19920,19921,19923,19925],{"class":237,"line":238},[235,19922,1270],{"class":1269},[235,19924,1273],{"class":1269},[235,19926,1276],{"class":499},[235,19928,19929,19932,19935,19938,19941,19943,19946,19948,19951,19954],{"class":237,"line":249},[235,19930,19931],{"class":1375},"    async",[235,19933,19934],{"class":495}," asyncData",[235,19936,19937],{"class":499},"({",[235,19939,19940],{"class":4527}," store",[235,19942,1404],{"class":499},[235,19944,19945],{"class":4527},"$content",[235,19947,1404],{"class":499},[235,19949,19950],{"class":4527}," params",[235,19952,19953],{"class":499}," })",[235,19955,1276],{"class":499},[235,19957,19958,19961,19964,19966,19969,19972,19974,19976,19979,19981,19983,19985,19987,19989,19992,19994,19996,19998,20000,20002,20004,20007,20009,20011,20013,20015,20018,20020,20023,20025,20027,20030,20032,20034,20037,20039],{"class":237,"line":259},[235,19959,19960],{"class":1375},"        const",[235,19962,19963],{"class":519}," count",[235,19965,4116],{"class":499},[235,19967,19968],{"class":1269}," await",[235,19970,19971],{"class":252}," $content",[235,19973,1705],{"class":495},[235,19975,1930],{"class":499},[235,19977,19978],{"class":495}," deep",[235,19980,500],{"class":499},[235,19982,5805],{"class":4702},[235,19984,14121],{"class":499},[235,19986,1715],{"class":495},[235,19988,1694],{"class":499},[235,19990,19991],{"class":252},"only",[235,19993,1705],{"class":495},[235,19995,1345],{"class":499},[235,19997,9125],{"class":245},[235,19999,1345],{"class":499},[235,20001,1715],{"class":495},[235,20003,1694],{"class":499},[235,20005,20006],{"class":252},"where",[235,20008,1705],{"class":495},[235,20010,1930],{"class":499},[235,20012,19626],{"class":495},[235,20014,14307],{"class":499},[235,20016,20017],{"class":495}," $contains",[235,20019,500],{"class":499},[235,20021,20022],{"class":519},"params",[235,20024,1694],{"class":499},[235,20026,18824],{"class":519},[235,20028,20029],{"class":499},"}}",[235,20031,1715],{"class":495},[235,20033,1694],{"class":499},[235,20035,20036],{"class":252},"fetch",[235,20038,2224],{"class":495},[235,20040,1348],{"class":499},[235,20042,20043],{"class":237,"line":266},[235,20044,263],{"emptyLinePlaceholder":262},[235,20046,20047,20049,20052,20054,20056,20058,20060,20062,20064,20066,20068,20070],{"class":237,"line":275},[235,20048,19960],{"class":1375},[235,20050,20051],{"class":519}," content",[235,20053,4116],{"class":499},[235,20055,19968],{"class":1269},[235,20057,19971],{"class":252},[235,20059,1705],{"class":495},[235,20061,1930],{"class":499},[235,20063,19978],{"class":495},[235,20065,500],{"class":499},[235,20067,5805],{"class":4702},[235,20069,14121],{"class":499},[235,20071,1953],{"class":495},[235,20073,20074,20077,20079,20082,20084,20086,20088,20090,20092,20094,20096,20098,20100,20102,20104,20106,20108,20110,20112,20114,20116,20118,20120,20122,20124,20126,20128,20130,20132,20135,20137,20139,20141,20143,20145,20147,20149,20151,20153],{"class":237,"line":283},[235,20075,20076],{"class":499},"        .",[235,20078,19991],{"class":252},[235,20080,20081],{"class":495},"([",[235,20083,1345],{"class":499},[235,20085,9125],{"class":245},[235,20087,1345],{"class":499},[235,20089,1404],{"class":499},[235,20091,1345],{"class":499},[235,20093,12404],{"class":245},[235,20095,1345],{"class":499},[235,20097,1404],{"class":499},[235,20099,1345],{"class":499},[235,20101,18745],{"class":245},[235,20103,1345],{"class":499},[235,20105,1404],{"class":499},[235,20107,1345],{"class":499},[235,20109,2098],{"class":245},[235,20111,1345],{"class":499},[235,20113,1404],{"class":499},[235,20115,1345],{"class":499},[235,20117,12443],{"class":245},[235,20119,1345],{"class":499},[235,20121,1404],{"class":499},[235,20123,1345],{"class":499},[235,20125,12465],{"class":245},[235,20127,1345],{"class":499},[235,20129,1404],{"class":499},[235,20131,1345],{"class":499},[235,20133,20134],{"class":245},"updatedAt",[235,20136,1345],{"class":499},[235,20138,1404],{"class":499},[235,20140,1345],{"class":499},[235,20142,18706],{"class":245},[235,20144,1345],{"class":499},[235,20146,1404],{"class":499},[235,20148,1345],{"class":499},[235,20150,10472],{"class":245},[235,20152,1345],{"class":499},[235,20154,20155],{"class":495},"])\n",[235,20157,20158,20160,20163,20165,20167,20170,20172,20174,20176,20179,20181],{"class":237,"line":291},[235,20159,20076],{"class":499},[235,20161,20162],{"class":252},"sortBy",[235,20164,1705],{"class":495},[235,20166,1345],{"class":499},[235,20168,20169],{"class":245},"createdAt",[235,20171,1345],{"class":499},[235,20173,1404],{"class":499},[235,20175,503],{"class":499},[235,20177,20178],{"class":245},"desc",[235,20180,1345],{"class":499},[235,20182,1953],{"class":495},[235,20184,20185,20187,20189,20191,20193,20195,20197,20199,20201,20203,20205,20207,20209,20211],{"class":237,"line":298},[235,20186,20076],{"class":499},[235,20188,20006],{"class":252},[235,20190,1705],{"class":495},[235,20192,1930],{"class":499},[235,20194,12465],{"class":495},[235,20196,14307],{"class":499},[235,20198,20017],{"class":495},[235,20200,500],{"class":499},[235,20202,20022],{"class":519},[235,20204,1694],{"class":499},[235,20206,18824],{"class":519},[235,20208,20029],{"class":499},[235,20210,10622],{"class":495},[235,20212,20213],{"class":3119},"\u002F\u002F ここ\n",[235,20215,20216,20218,20221,20223,20225,20227,20229,20232,20234,20237,20239,20241,20243,20246],{"class":237,"line":380},[235,20217,20076],{"class":499},[235,20219,20220],{"class":252},"skip",[235,20222,1705],{"class":495},[235,20224,4582],{"class":2836},[235,20226,1715],{"class":495},[235,20228,1694],{"class":499},[235,20230,20231],{"class":252},"limit",[235,20233,1705],{"class":495},[235,20235,20236],{"class":519},"store",[235,20238,1694],{"class":499},[235,20240,19571],{"class":519},[235,20242,1694],{"class":499},[235,20244,20245],{"class":519},"indexPerPage",[235,20247,1953],{"class":495},[235,20249,20250,20252,20254,20256],{"class":237,"line":465},[235,20251,20076],{"class":499},[235,20253,20036],{"class":252},[235,20255,2224],{"class":495},[235,20257,1348],{"class":499},[235,20259,20260],{"class":237,"line":590},[235,20261,263],{"emptyLinePlaceholder":262},[235,20263,20264,20266],{"class":237,"line":604},[235,20265,19579],{"class":1269},[235,20267,1276],{"class":499},[235,20269,20270,20272],{"class":237,"line":612},[235,20271,7552],{"class":499},[235,20273,20274],{"class":495},"        content,\n",[235,20276,20277,20280],{"class":237,"line":623},[235,20278,20279],{"class":495},"        count:count.length",[235,20281,20282],{"class":499},"`\n",[235,20284,20285],{"class":237,"line":634},[235,20286,4086],{"class":495},[235,20288,20289],{"class":237,"line":641},[235,20290,4091],{"class":495},[235,20292,20293],{"class":237,"line":653},[235,20294,1317],{"class":495},[13,20296,20297,20298,20301,20302,4237,20305,20308],{},"まずしっかりと記事のデータとして",[39,20299,20300],{},"'tag'","を指定して、",[39,20303,20304],{},".where({tag:{ $contains:params.slug}})",[39,20306,20307],{},"params.slug","からURLのスラグを取得して、それが配列内に含まれているかを確かめています。その条件に合致した投稿、すなわち目的のタグを持っている記事のみを取得することができます。",[13,20310,20311],{},"後は一覧ページの実装で説明した通りにテンプレートを記述するなり、ページングを実装すれば完了です。",[74,20313,20314],{"id":20314},"静的書き出しの時はどうなるのか",[13,20316,20317,20318,20321,20322,20324,20325,20327],{},"このカテゴリーのルートはNuxtが知らないので、nuxt.config.jsで追加ルートとして記述しておく必要があります。ただし、私のサイトのようにサイドメニューにずっとリンクがある場合はとくに対策はしなくてもいいです。Nuxtの静的書き出しは",[39,20319,20320],{},"nuxt-link","を辿ってルートを解決しているそうで、自動的にタグ・カテゴリーのルートを書き出してくれました。なので",[39,20323,20320],{},"でタグのリンクを貼って、",[39,20326,19889],{}," の構成が正しければ特に心配ありません。",[74,20329,20331],{"id":20330},"以上でカテゴリータグ機能を実装","以上でカテゴリー。タグ機能を実装",[13,20333,20334],{},"前回までの記事詳細→一覧の作成と似ていましたが、",[17,20336,20337,20340,20346],{},[20,20338,20339],{},"記事に新しいメタデータを設定",[20,20341,20342,20345],{},[39,20343,20344],{},"where()","で特定のタグ・カテゴリーを取得する",[20,20347,20348],{},"store・外部ファイルで管理する",[13,20350,20351],{},"という点で少し違っていました。今回はカテゴリー・タグといったものですが使い方によってはいろんな分類方法があると思います。ぜひチャレンジしてみてください。次回は最後で、ブログとしてデプロイする前に設定すべきこと、アナリティクスやアドセンスの貼り方について解説します。",[2399,20353,20354],{},"html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sbqyR, html code.shiki .sbqyR{--shiki-default:#FF9CAC}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}",{"title":231,"searchDepth":259,"depth":259,"links":20356},[20357,20358,20359,20360,20361,20362,20363],{"id":18626,"depth":249,"text":18626},{"id":18638,"depth":249,"text":18639},{"id":18773,"depth":249,"text":18774},{"id":19872,"depth":249,"text":19873},{"id":19905,"depth":249,"text":19906},{"id":20314,"depth":249,"text":20314},{"id":20330,"depth":249,"text":20331},[2427],"2021-05-09","Nuxt Content × SSG で作る静的ブログ。カテゴリーとタグ機能",{},"\u002Fseries\u002Fnuxt-content-blog-4",{"title":18609,"description":20366},"nuxt-content-blog","Nuxt Content × SSG で作る静的ブログ。","series\u002Fnuxt-content-blog-4",[1262,18699],"_mix\u002Flogo-dark.jpg","SRildu2cH6w8PGbcMmWirBzP0VR8lSIzk3eFtii40vY",{"id":20377,"title":20378,"body":20379,"category":22390,"createdAt":22391,"description":22392,"extension":2430,"index":259,"meta":22393,"navigation":262,"path":22394,"publish":262,"seo":22395,"series":20370,"seriesTitle":20371,"stem":22396,"tag":22397,"thumbnail":20374,"updatedAt":2439,"__hash__":22398},"series\u002Fseries\u002Fnuxt-content-blog-3.md","Nuxt Content × SSG で作る静的ブログ。３：記事一覧ページとページング実装",{"type":10,"value":20380,"toc":22377},[20381,20387,20395,20398,20401,20404,20407,20413,20427,20433,20442,20445,20454,20784,20806,20820,20831,20844,20847,20850,20859,20865,20875,22030,22033,22037,22057,22060,22115,22120,22123,22126,22134,22137,22319,22324,22327,22332,22343,22346,22350,22360,22366,22369,22371,22374],[13,20382,18614,20383,20386],{},[197,20384,18618],{"href":20385},"\u002Fseries\u002Fnuxt-content-blog\u002F2","は詳細ページの実装と静的書き出しを行いました。今回の記事では",[17,20388,20389,20392],{},[20,20390,20391],{},"記事一覧ページの作成",[20,20393,20394],{},"ページング機能",[13,20396,20397],{},"について解説していきます。それでは早速いきましょう。",[74,20399,20400],{"id":20400},"articlesの一覧ページを作る",[81,20402,20403],{"id":20403},"pagesディレクトリを設定する",[13,20405,20406],{},"詳細ページのルーティングを作るために以前は以下のようなディレクトリの設定をしました。",[226,20408,20411],{"className":20409,"code":20410,"language":934},[932],"├── pages\n│   ├── articles\n│   　   ├── _slug.vue\n",[39,20412,20410],{"__ignoreMap":231},[13,20414,12545,20415,20418,20419,20422,20423,20426],{},[39,20416,20417],{},"\u002Farticles\u002F{sulg}","というURLが有効になります。一覧ページは",[39,20420,20421],{},"\u002Farticles\u002F","というルートで",[39,20424,20425],{},"content\u002Farticles\u002F","配下の原稿が一覧となって見れるページです。しかし上記の設定では表示されないので以下のようにします。",[226,20428,20431],{"className":20429,"code":20430,"language":934},[932],"├── pages\n│   ├── articles\n│   　   ├── index.vue #追加\n│   　   ├── _slug.vue\n",[39,20432,20430],{"__ignoreMap":231},[13,20434,20435,20438,20439,20441],{},[39,20436,20437],{},"index.vue","というものを足しました。このファイルは",[39,20440,20421],{},"というルートに対応しています。ディレクトリの設定は以上となります。",[81,20443,20444],{"id":20444},"一覧のデータを取得してレンダーする",[13,20446,1243,20447,20449,20450,20453],{},[39,20448,20437],{},"にソースを書いていきましょう。詳細ページでは特定のパスに対応するコンテンツを取得していましたが、一覧ページでは",[39,20451,20452],{},"articles","のコンテンツを15件ほど取得するようにしましょう。とりあえずソースを載せます。",[226,20455,20458],{"className":1472,"code":20456,"filename":20457,"language":1208,"meta":231,"style":231},"\u003Ctemplate>\n    \u003Cdiv class=\"\">\n        \u003Ch1>記事一覧\u003C\u002Fh1>\n        \u003Cul>\n        \u003Cli v-for=\"(c,index) in content\" :key=\"index\">\n            \u003Cnuxt-link :to=\"c.path\">{{c.title}}\u003C\u002Fnuxt-link>\n        \u003C\u002Fli>\n        \u003C\u002Ful>\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\nexport default {\n  async asyncData({ store,$content, params }) {\n    const content = await $content('articles')\n    .only(['title','path'])\n    .sortBy('createdAt', 'desc')\n    .skip(0).limit(15)\n    .fetch();\n\n    return {\n      content,\n    }\n  }\n}\n\u003C\u002Fscript>\n","page\u002Farticles\u002Findex.vue",[39,20459,20460,20468,20482,20500,20508,20539,20568,20576,20584,20592,20600,20604,20612,20620,20643,20665,20690,20714,20737,20747,20751,20757,20764,20768,20772,20776],{"__ignoreMap":231},[235,20461,20462,20464,20466],{"class":237,"line":238},[235,20463,1481],{"class":499},[235,20465,1484],{"class":495},[235,20467,1487],{"class":499},[235,20469,20470,20472,20474,20476,20478,20480],{"class":237,"line":249},[235,20471,1492],{"class":499},[235,20473,1225],{"class":495},[235,20475,8005],{"class":1375},[235,20477,1382],{"class":499},[235,20479,13711],{"class":499},[235,20481,1487],{"class":499},[235,20483,20484,20486,20489,20491,20494,20496,20498],{"class":237,"line":259},[235,20485,1506],{"class":499},[235,20487,20488],{"class":495},"h1",[235,20490,1524],{"class":499},[235,20492,20493],{"class":519},"記事一覧",[235,20495,1530],{"class":499},[235,20497,20488],{"class":495},[235,20499,1487],{"class":499},[235,20501,20502,20504,20506],{"class":237,"line":266},[235,20503,1506],{"class":499},[235,20505,17],{"class":495},[235,20507,1487],{"class":499},[235,20509,20510,20512,20514,20517,20519,20521,20524,20526,20529,20531,20533,20535,20537],{"class":237,"line":275},[235,20511,1506],{"class":499},[235,20513,20],{"class":495},[235,20515,20516],{"class":1375}," v-for",[235,20518,1382],{"class":499},[235,20520,1517],{"class":499},[235,20522,20523],{"class":245},"(c,index) in content",[235,20525,1517],{"class":499},[235,20527,20528],{"class":1375}," :key",[235,20530,1382],{"class":499},[235,20532,1517],{"class":499},[235,20534,10472],{"class":245},[235,20536,1517],{"class":499},[235,20538,1487],{"class":499},[235,20540,20541,20543,20545,20548,20550,20552,20555,20557,20559,20562,20564,20566],{"class":237,"line":283},[235,20542,9208],{"class":499},[235,20544,20320],{"class":495},[235,20546,20547],{"class":1375}," :to",[235,20549,1382],{"class":499},[235,20551,1517],{"class":499},[235,20553,20554],{"class":245},"c.path",[235,20556,1517],{"class":499},[235,20558,1524],{"class":499},[235,20560,20561],{"class":519},"{{c.title}}",[235,20563,1530],{"class":499},[235,20565,20320],{"class":495},[235,20567,1487],{"class":499},[235,20569,20570,20572,20574],{"class":237,"line":291},[235,20571,9278],{"class":499},[235,20573,20],{"class":495},[235,20575,1487],{"class":499},[235,20577,20578,20580,20582],{"class":237,"line":298},[235,20579,9278],{"class":499},[235,20581,17],{"class":495},[235,20583,1487],{"class":499},[235,20585,20586,20588,20590],{"class":237,"line":380},[235,20587,1539],{"class":499},[235,20589,1225],{"class":495},[235,20591,1487],{"class":499},[235,20593,20594,20596,20598],{"class":237,"line":465},[235,20595,1530],{"class":499},[235,20597,1484],{"class":495},[235,20599,1487],{"class":499},[235,20601,20602],{"class":237,"line":590},[235,20603,263],{"emptyLinePlaceholder":262},[235,20605,20606,20608,20610],{"class":237,"line":604},[235,20607,1481],{"class":499},[235,20609,1558],{"class":495},[235,20611,1487],{"class":499},[235,20613,20614,20616,20618],{"class":237,"line":612},[235,20615,1270],{"class":1269},[235,20617,1273],{"class":1269},[235,20619,1276],{"class":499},[235,20621,20622,20625,20627,20629,20631,20633,20635,20637,20639,20641],{"class":237,"line":623},[235,20623,20624],{"class":1375},"  async",[235,20626,19934],{"class":495},[235,20628,19937],{"class":499},[235,20630,19940],{"class":4527},[235,20632,1404],{"class":499},[235,20634,19945],{"class":4527},[235,20636,1404],{"class":499},[235,20638,19950],{"class":4527},[235,20640,19953],{"class":499},[235,20642,1276],{"class":499},[235,20644,20645,20647,20649,20651,20653,20655,20657,20659,20661,20663],{"class":237,"line":634},[235,20646,4540],{"class":1375},[235,20648,20051],{"class":519},[235,20650,4116],{"class":499},[235,20652,19968],{"class":1269},[235,20654,19971],{"class":252},[235,20656,1705],{"class":495},[235,20658,1345],{"class":499},[235,20660,20452],{"class":245},[235,20662,1345],{"class":499},[235,20664,1953],{"class":495},[235,20666,20667,20670,20672,20674,20676,20678,20680,20682,20684,20686,20688],{"class":237,"line":641},[235,20668,20669],{"class":499},"    .",[235,20671,19991],{"class":252},[235,20673,20081],{"class":495},[235,20675,1345],{"class":499},[235,20677,9125],{"class":245},[235,20679,1345],{"class":499},[235,20681,1404],{"class":499},[235,20683,1345],{"class":499},[235,20685,2098],{"class":245},[235,20687,1345],{"class":499},[235,20689,20155],{"class":495},[235,20691,20692,20694,20696,20698,20700,20702,20704,20706,20708,20710,20712],{"class":237,"line":653},[235,20693,20669],{"class":499},[235,20695,20162],{"class":252},[235,20697,1705],{"class":495},[235,20699,1345],{"class":499},[235,20701,20169],{"class":245},[235,20703,1345],{"class":499},[235,20705,1404],{"class":499},[235,20707,503],{"class":499},[235,20709,20178],{"class":245},[235,20711,1345],{"class":499},[235,20713,1953],{"class":495},[235,20715,20716,20718,20720,20722,20724,20726,20728,20730,20732,20735],{"class":237,"line":661},[235,20717,20669],{"class":499},[235,20719,20220],{"class":252},[235,20721,1705],{"class":495},[235,20723,4582],{"class":2836},[235,20725,1715],{"class":495},[235,20727,1694],{"class":499},[235,20729,20231],{"class":252},[235,20731,1705],{"class":495},[235,20733,20734],{"class":2836},"15",[235,20736,1953],{"class":495},[235,20738,20739,20741,20743,20745],{"class":237,"line":670},[235,20740,20669],{"class":499},[235,20742,20036],{"class":252},[235,20744,2224],{"class":495},[235,20746,1348],{"class":499},[235,20748,20749],{"class":237,"line":678},[235,20750,263],{"emptyLinePlaceholder":262},[235,20752,20753,20755],{"class":237,"line":686},[235,20754,9697],{"class":1269},[235,20756,1276],{"class":499},[235,20758,20759,20762],{"class":237,"line":694},[235,20760,20761],{"class":519},"      content",[235,20763,1984],{"class":499},[235,20765,20766],{"class":237,"line":702},[235,20767,2181],{"class":499},[235,20769,20770],{"class":237,"line":712},[235,20771,12914],{"class":499},[235,20773,20774],{"class":237,"line":723},[235,20775,1317],{"class":499},[235,20777,20778,20780,20782],{"class":237,"line":730},[235,20779,1530],{"class":499},[235,20781,1558],{"class":495},[235,20783,1487],{"class":499},[13,20785,5686,20786,6554,20789,20791,20792,20795,20796,20799,20800,20802,20803,20805],{},[39,20787,20788],{},"$content('articles')",[39,20790,20452],{},"配下のコンテンツを読む指定をします。そして",[39,20793,20794],{},".only(['title','path'])","を使用することでtitleとpathのみのデータを取得することができます。この",[39,20797,20798],{},"only()","を指定しない場合、",[39,20801,4677],{},"プロパティという原稿内容も取得してしまいます。原稿がボリューミーなほど取得コストが大きくなり、静的書き出しなどにも影響されます。そのため一覧などでは",[39,20804,20798],{},"を使用して必要最低限のプロパティを使用した方がいいです。",[13,20807,20808,20811,20812,20815,20816,20819],{},[39,20809,20810],{},"sortBy()","にて特定プロパティでソートし、後のページングで使いますが",[39,20813,20814],{},".skip(0).limit(15)","にて15件の記事を取得します。",[39,20817,20818],{},"asyncData()","内で記事を取得して、それをリストで出力します。",[1225,20821,20823,20826,20827,20830],{"className":20822},[1228,2914],[39,20824,20825],{},"$content()","に対して加えることが可能なメソッドは",[197,20828,7984],{"href":20829,"target":2918},"https:\u002F\u002Fcontent.nuxtjs.org\u002Fja\u002Ffetching","で確認できます。\n",[13,20832,20833,20834,4237,20837,13500,20840,20843],{},"Nuxt.jsで内部リンクを作成する時は",[39,20835,20836],{},"\u003Cnuxt-link>",[39,20838,20839],{},"to",[39,20841,20842],{},"content.path","を指定することで詳細ページに移動できるようになります。",[13,20845,20846],{},"一覧ページはこれぐらいで実装できます。今は最初から15件しか取得しないので、大量にある時はページングができるようにしましょう。",[74,20848,20849],{"id":20849},"ページングを実装する",[13,20851,20852,20853,20856,20857,13519],{},"私のサイトでは",[39,20854,20855],{},"\u002Farticles\u002Fpage\u002F2","の様なルートで対応しています。この様なルートを設定する場合は以下のように",[39,20858,19889],{},[226,20860,20863],{"className":20861,"code":20862,"language":934},[932],"├── pages\n│   ├── articles\n│   　   ├── index.vue \n│   　   ├── _slug.vue\n│   　   ├── pages          #追加\n│   　        ├──_id.vue    #追加\n",[39,20864,20862],{"__ignoreMap":231},[13,20866,20867,20870,20871,20874],{},[39,20868,20869],{},"_id.vue","を作成することで",[39,20872,20873],{},"\u002Farticles\u002Fpage\u002F{n}","という動的ルートが作成されます。そこでは以下のように設定します。",[226,20876,20879],{"className":1472,"code":20877,"filename":20878,"language":1208,"meta":231,"style":231},"\u003Ctemplate>\n    \u003Cdiv class=\"\">\n        \u003Ch1>記事一覧\u003C\u002Fh1>\n        \u003Cul>\n            \u003Cli v-for=\"(c,index) in content\" :key=\"index\">\n                \u003Cnuxt-link :to=\"c.path\">{{c.title}}\u003C\u002Fnuxt-link>\n            \u003C\u002Fli>\n        \u003C\u002Ful>\n        \u003Cul class=\"p-pagenation-container\">\n            \u003Cli class=\"c-pagenation-unit\" v-for=\"(pg) in num\" :key=\"pg.num\">\n                \u003Cnuxt-link v-if=\"pg.pg\" :to=\"'\u002Farticles\u002Fpage\u002F'+pg.num\" :class=\"(current == pg.num)?'is-current':''\">\n                    {{pg.num}}\n                \u003C\u002Fnuxt-link>\n                \u003Cspan v-else>\n                    {{pg.num}}\n                \u003C\u002Fspan>\n            \u003C\u002Fli>\n        \u003C\u002Ful>\n    \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\nexport default {\n    validate({ redirect,params }) {\n        if(\u002F[0-9]+\u002F.test(params.id)) return true;\n        return redirect('\u002Farticles')\n    },\n    async asyncData({ store,$content, params }) {\n        const count = await $content('articles').only('title').fetch();\n        const current = params.id;\n        if(current > Math.ceil( count.length \u002F store.state.indexPerPage)) redirect('\u002Farticles');\n\n        const from = store.state.indexPerPage * (params.id - 1);\n        const to = store.state.indexPerPage * params.id;\n\n        const content = await $content('articles')\n        .only(['title','path'])\n        .sortBy('createdAt', 'desc')\n        .skip(from).limit(to)\n        .fetch();\n\n        return {\n            content,\n            current,\n            count:count.length\n        }\n    },\n    computed:{\n        max(){\n            return Math.ceil( this.$route.params.id \u002F 15);\n        },\n        num(){\n            let tmp = [];\n            for(let n=1; n\u003C=this.max;n++){\n                if(n == 1 || n == this.max){\n                    tmp.push({pg:true,num:n});\n                    continue;\n                }\n                if((this.current - 2 \u003C= n) && (n \u003C= this.current + 2)){\n                    tmp.push({pg:true,num:n})\n                    continue;\n                }\n                if((this.current - 2 - 1 == n) || (n == this.current + 2 + 1) ){\n                   tmp.push({pg:false,num:\"...\"})\n                    continue;\n                }\n            }\n            return tmp;\n        }\n    },\n}\n\u003C\u002Fscript>\n","page\u002Farticles\u002Fpage\u002F_id.vue",[39,20880,20881,20889,20903,20919,20927,20955,20982,20990,20998,21017,21058,21101,21106,21115,21126,21130,21138,21146,21154,21162,21170,21174,21182,21190,21208,21245,21262,21266,21288,21332,21349,21406,21410,21448,21476,21480,21502,21526,21550,21572,21582,21586,21592,21599,21606,21620,21624,21628,21635,21643,21678,21682,21689,21703,21741,21771,21806,21813,21817,21861,21891,21897,21901,21951,21988,21994,21998,22002,22010,22014,22018,22022],{"__ignoreMap":231},[235,20882,20883,20885,20887],{"class":237,"line":238},[235,20884,1481],{"class":499},[235,20886,1484],{"class":495},[235,20888,1487],{"class":499},[235,20890,20891,20893,20895,20897,20899,20901],{"class":237,"line":249},[235,20892,1492],{"class":499},[235,20894,1225],{"class":495},[235,20896,8005],{"class":1375},[235,20898,1382],{"class":499},[235,20900,13711],{"class":499},[235,20902,1487],{"class":499},[235,20904,20905,20907,20909,20911,20913,20915,20917],{"class":237,"line":259},[235,20906,1506],{"class":499},[235,20908,20488],{"class":495},[235,20910,1524],{"class":499},[235,20912,20493],{"class":519},[235,20914,1530],{"class":499},[235,20916,20488],{"class":495},[235,20918,1487],{"class":499},[235,20920,20921,20923,20925],{"class":237,"line":266},[235,20922,1506],{"class":499},[235,20924,17],{"class":495},[235,20926,1487],{"class":499},[235,20928,20929,20931,20933,20935,20937,20939,20941,20943,20945,20947,20949,20951,20953],{"class":237,"line":275},[235,20930,9208],{"class":499},[235,20932,20],{"class":495},[235,20934,20516],{"class":1375},[235,20936,1382],{"class":499},[235,20938,1517],{"class":499},[235,20940,20523],{"class":245},[235,20942,1517],{"class":499},[235,20944,20528],{"class":1375},[235,20946,1382],{"class":499},[235,20948,1517],{"class":499},[235,20950,10472],{"class":245},[235,20952,1517],{"class":499},[235,20954,1487],{"class":499},[235,20956,20957,20960,20962,20964,20966,20968,20970,20972,20974,20976,20978,20980],{"class":237,"line":283},[235,20958,20959],{"class":499},"                \u003C",[235,20961,20320],{"class":495},[235,20963,20547],{"class":1375},[235,20965,1382],{"class":499},[235,20967,1517],{"class":499},[235,20969,20554],{"class":245},[235,20971,1517],{"class":499},[235,20973,1524],{"class":499},[235,20975,20561],{"class":519},[235,20977,1530],{"class":499},[235,20979,20320],{"class":495},[235,20981,1487],{"class":499},[235,20983,20984,20986,20988],{"class":237,"line":291},[235,20985,9241],{"class":499},[235,20987,20],{"class":495},[235,20989,1487],{"class":499},[235,20991,20992,20994,20996],{"class":237,"line":298},[235,20993,9278],{"class":499},[235,20995,17],{"class":495},[235,20997,1487],{"class":499},[235,20999,21000,21002,21004,21006,21008,21010,21013,21015],{"class":237,"line":380},[235,21001,1506],{"class":499},[235,21003,17],{"class":495},[235,21005,8005],{"class":1375},[235,21007,1382],{"class":499},[235,21009,1517],{"class":499},[235,21011,21012],{"class":245},"p-pagenation-container",[235,21014,1517],{"class":499},[235,21016,1487],{"class":499},[235,21018,21019,21021,21023,21025,21027,21029,21032,21034,21036,21038,21040,21043,21045,21047,21049,21051,21054,21056],{"class":237,"line":465},[235,21020,9208],{"class":499},[235,21022,20],{"class":495},[235,21024,8005],{"class":1375},[235,21026,1382],{"class":499},[235,21028,1517],{"class":499},[235,21030,21031],{"class":245},"c-pagenation-unit",[235,21033,1517],{"class":499},[235,21035,20516],{"class":1375},[235,21037,1382],{"class":499},[235,21039,1517],{"class":499},[235,21041,21042],{"class":245},"(pg) in num",[235,21044,1517],{"class":499},[235,21046,20528],{"class":1375},[235,21048,1382],{"class":499},[235,21050,1517],{"class":499},[235,21052,21053],{"class":245},"pg.num",[235,21055,1517],{"class":499},[235,21057,1487],{"class":499},[235,21059,21060,21062,21064,21067,21069,21071,21074,21076,21078,21080,21082,21085,21087,21090,21092,21094,21097,21099],{"class":237,"line":590},[235,21061,20959],{"class":499},[235,21063,20320],{"class":495},[235,21065,21066],{"class":1375}," v-if",[235,21068,1382],{"class":499},[235,21070,1517],{"class":499},[235,21072,21073],{"class":245},"pg.pg",[235,21075,1517],{"class":499},[235,21077,20547],{"class":1375},[235,21079,1382],{"class":499},[235,21081,1517],{"class":499},[235,21083,21084],{"class":245},"'\u002Farticles\u002Fpage\u002F'+pg.num",[235,21086,1517],{"class":499},[235,21088,21089],{"class":1375}," :class",[235,21091,1382],{"class":499},[235,21093,1517],{"class":499},[235,21095,21096],{"class":245},"(current == pg.num)?'is-current':''",[235,21098,1517],{"class":499},[235,21100,1487],{"class":499},[235,21102,21103],{"class":237,"line":604},[235,21104,21105],{"class":519},"                    {{pg.num}}\n",[235,21107,21108,21111,21113],{"class":237,"line":612},[235,21109,21110],{"class":499},"                \u003C\u002F",[235,21112,20320],{"class":495},[235,21114,1487],{"class":499},[235,21116,21117,21119,21121,21124],{"class":237,"line":623},[235,21118,20959],{"class":499},[235,21120,235],{"class":495},[235,21122,21123],{"class":1375}," v-else",[235,21125,1487],{"class":499},[235,21127,21128],{"class":237,"line":634},[235,21129,21105],{"class":519},[235,21131,21132,21134,21136],{"class":237,"line":641},[235,21133,21110],{"class":499},[235,21135,235],{"class":495},[235,21137,1487],{"class":499},[235,21139,21140,21142,21144],{"class":237,"line":653},[235,21141,9241],{"class":499},[235,21143,20],{"class":495},[235,21145,1487],{"class":499},[235,21147,21148,21150,21152],{"class":237,"line":661},[235,21149,9278],{"class":499},[235,21151,17],{"class":495},[235,21153,1487],{"class":499},[235,21155,21156,21158,21160],{"class":237,"line":670},[235,21157,1539],{"class":499},[235,21159,1225],{"class":495},[235,21161,1487],{"class":499},[235,21163,21164,21166,21168],{"class":237,"line":678},[235,21165,1530],{"class":499},[235,21167,1484],{"class":495},[235,21169,1487],{"class":499},[235,21171,21172],{"class":237,"line":686},[235,21173,263],{"emptyLinePlaceholder":262},[235,21175,21176,21178,21180],{"class":237,"line":694},[235,21177,1481],{"class":499},[235,21179,1558],{"class":495},[235,21181,1487],{"class":499},[235,21183,21184,21186,21188],{"class":237,"line":702},[235,21185,1270],{"class":1269},[235,21187,1273],{"class":1269},[235,21189,1276],{"class":499},[235,21191,21192,21195,21197,21200,21202,21204,21206],{"class":237,"line":712},[235,21193,21194],{"class":495},"    validate",[235,21196,19937],{"class":499},[235,21198,21199],{"class":4527}," redirect",[235,21201,1404],{"class":499},[235,21203,20022],{"class":4527},[235,21205,19953],{"class":499},[235,21207,1276],{"class":499},[235,21209,21210,21213,21215,21218,21221,21224,21226,21228,21230,21232,21234,21236,21239,21241,21243],{"class":237,"line":723},[235,21211,21212],{"class":1269},"        if",[235,21214,1705],{"class":495},[235,21216,21217],{"class":499},"\u002F[",[235,21219,21220],{"class":245},"0-9",[235,21222,21223],{"class":499},"]+\u002F",[235,21225,1694],{"class":499},[235,21227,15969],{"class":252},[235,21229,1705],{"class":495},[235,21231,20022],{"class":519},[235,21233,1694],{"class":499},[235,21235,9785],{"class":519},[235,21237,21238],{"class":495},")) ",[235,21240,10439],{"class":1269},[235,21242,5805],{"class":4702},[235,21244,1348],{"class":499},[235,21246,21247,21249,21251,21253,21255,21258,21260],{"class":237,"line":730},[235,21248,19579],{"class":1269},[235,21250,21199],{"class":252},[235,21252,1705],{"class":495},[235,21254,1345],{"class":499},[235,21256,21257],{"class":245},"\u002Farticles",[235,21259,1345],{"class":499},[235,21261,1953],{"class":495},[235,21263,21264],{"class":237,"line":741},[235,21265,4091],{"class":499},[235,21267,21268,21270,21272,21274,21276,21278,21280,21282,21284,21286],{"class":237,"line":752},[235,21269,19931],{"class":1375},[235,21271,19934],{"class":495},[235,21273,19937],{"class":499},[235,21275,19940],{"class":4527},[235,21277,1404],{"class":499},[235,21279,19945],{"class":4527},[235,21281,1404],{"class":499},[235,21283,19950],{"class":4527},[235,21285,19953],{"class":499},[235,21287,1276],{"class":499},[235,21289,21290,21292,21294,21296,21298,21300,21302,21304,21306,21308,21310,21312,21314,21316,21318,21320,21322,21324,21326,21328,21330],{"class":237,"line":763},[235,21291,19960],{"class":1375},[235,21293,19963],{"class":519},[235,21295,4116],{"class":499},[235,21297,19968],{"class":1269},[235,21299,19971],{"class":252},[235,21301,1705],{"class":495},[235,21303,1345],{"class":499},[235,21305,20452],{"class":245},[235,21307,1345],{"class":499},[235,21309,1715],{"class":495},[235,21311,1694],{"class":499},[235,21313,19991],{"class":252},[235,21315,1705],{"class":495},[235,21317,1345],{"class":499},[235,21319,9125],{"class":245},[235,21321,1345],{"class":499},[235,21323,1715],{"class":495},[235,21325,1694],{"class":499},[235,21327,20036],{"class":252},[235,21329,2224],{"class":495},[235,21331,1348],{"class":499},[235,21333,21334,21336,21339,21341,21343,21345,21347],{"class":237,"line":774},[235,21335,19960],{"class":1375},[235,21337,21338],{"class":519}," current",[235,21340,4116],{"class":499},[235,21342,19950],{"class":519},[235,21344,1694],{"class":499},[235,21346,9785],{"class":519},[235,21348,1348],{"class":499},[235,21350,21351,21353,21355,21358,21360,21362,21364,21367,21370,21373,21375,21377,21379,21381,21383,21385,21387,21389,21391,21394,21396,21398,21400,21402,21404],{"class":237,"line":785},[235,21352,21212],{"class":1269},[235,21354,1705],{"class":495},[235,21356,21357],{"class":519},"current",[235,21359,13744],{"class":499},[235,21361,9924],{"class":519},[235,21363,1694],{"class":499},[235,21365,21366],{"class":252},"ceil",[235,21368,21369],{"class":495},"( ",[235,21371,21372],{"class":519},"count",[235,21374,1694],{"class":499},[235,21376,10080],{"class":519},[235,21378,4040],{"class":499},[235,21380,19940],{"class":519},[235,21382,1694],{"class":499},[235,21384,19571],{"class":519},[235,21386,1694],{"class":499},[235,21388,20245],{"class":519},[235,21390,21238],{"class":495},[235,21392,21393],{"class":252},"redirect",[235,21395,1705],{"class":495},[235,21397,1345],{"class":499},[235,21399,21257],{"class":245},[235,21401,1345],{"class":499},[235,21403,1715],{"class":495},[235,21405,1348],{"class":499},[235,21407,21408],{"class":237,"line":794},[235,21409,263],{"emptyLinePlaceholder":262},[235,21411,21412,21414,21417,21419,21421,21423,21425,21427,21429,21432,21434,21436,21438,21440,21442,21444,21446],{"class":237,"line":806},[235,21413,19960],{"class":1375},[235,21415,21416],{"class":519}," from",[235,21418,4116],{"class":499},[235,21420,19940],{"class":519},[235,21422,1694],{"class":499},[235,21424,19571],{"class":519},[235,21426,1694],{"class":499},[235,21428,20245],{"class":519},[235,21430,21431],{"class":499}," *",[235,21433,10342],{"class":495},[235,21435,20022],{"class":519},[235,21437,1694],{"class":499},[235,21439,9785],{"class":519},[235,21441,10576],{"class":499},[235,21443,8648],{"class":2836},[235,21445,1715],{"class":495},[235,21447,1348],{"class":499},[235,21449,21450,21452,21454,21456,21458,21460,21462,21464,21466,21468,21470,21472,21474],{"class":237,"line":815},[235,21451,19960],{"class":1375},[235,21453,1512],{"class":519},[235,21455,4116],{"class":499},[235,21457,19940],{"class":519},[235,21459,1694],{"class":499},[235,21461,19571],{"class":519},[235,21463,1694],{"class":499},[235,21465,20245],{"class":519},[235,21467,21431],{"class":499},[235,21469,19950],{"class":519},[235,21471,1694],{"class":499},[235,21473,9785],{"class":519},[235,21475,1348],{"class":499},[235,21477,21478],{"class":237,"line":823},[235,21479,263],{"emptyLinePlaceholder":262},[235,21481,21482,21484,21486,21488,21490,21492,21494,21496,21498,21500],{"class":237,"line":833},[235,21483,19960],{"class":1375},[235,21485,20051],{"class":519},[235,21487,4116],{"class":499},[235,21489,19968],{"class":1269},[235,21491,19971],{"class":252},[235,21493,1705],{"class":495},[235,21495,1345],{"class":499},[235,21497,20452],{"class":245},[235,21499,1345],{"class":499},[235,21501,1953],{"class":495},[235,21503,21504,21506,21508,21510,21512,21514,21516,21518,21520,21522,21524],{"class":237,"line":3537},[235,21505,20076],{"class":499},[235,21507,19991],{"class":252},[235,21509,20081],{"class":495},[235,21511,1345],{"class":499},[235,21513,9125],{"class":245},[235,21515,1345],{"class":499},[235,21517,1404],{"class":499},[235,21519,1345],{"class":499},[235,21521,2098],{"class":245},[235,21523,1345],{"class":499},[235,21525,20155],{"class":495},[235,21527,21528,21530,21532,21534,21536,21538,21540,21542,21544,21546,21548],{"class":237,"line":3542},[235,21529,20076],{"class":499},[235,21531,20162],{"class":252},[235,21533,1705],{"class":495},[235,21535,1345],{"class":499},[235,21537,20169],{"class":245},[235,21539,1345],{"class":499},[235,21541,1404],{"class":499},[235,21543,503],{"class":499},[235,21545,20178],{"class":245},[235,21547,1345],{"class":499},[235,21549,1953],{"class":495},[235,21551,21552,21554,21556,21558,21560,21562,21564,21566,21568,21570],{"class":237,"line":3547},[235,21553,20076],{"class":499},[235,21555,20220],{"class":252},[235,21557,1705],{"class":495},[235,21559,1337],{"class":519},[235,21561,1715],{"class":495},[235,21563,1694],{"class":499},[235,21565,20231],{"class":252},[235,21567,1705],{"class":495},[235,21569,20839],{"class":519},[235,21571,1953],{"class":495},[235,21573,21574,21576,21578,21580],{"class":237,"line":3553},[235,21575,20076],{"class":499},[235,21577,20036],{"class":252},[235,21579,2224],{"class":495},[235,21581,1348],{"class":499},[235,21583,21584],{"class":237,"line":3558},[235,21585,263],{"emptyLinePlaceholder":262},[235,21587,21588,21590],{"class":237,"line":3564},[235,21589,19579],{"class":1269},[235,21591,1276],{"class":499},[235,21593,21594,21597],{"class":237,"line":4},[235,21595,21596],{"class":519},"            content",[235,21598,1984],{"class":499},[235,21600,21601,21604],{"class":237,"line":3575},[235,21602,21603],{"class":519},"            current",[235,21605,1984],{"class":499},[235,21607,21608,21611,21613,21615,21617],{"class":237,"line":3581},[235,21609,21610],{"class":495},"            count",[235,21612,500],{"class":499},[235,21614,21372],{"class":519},[235,21616,1694],{"class":499},[235,21618,21619],{"class":519},"length\n",[235,21621,21622],{"class":237,"line":3587},[235,21623,4086],{"class":499},[235,21625,21626],{"class":237,"line":3593},[235,21627,4091],{"class":499},[235,21629,21630,21633],{"class":237,"line":3599},[235,21631,21632],{"class":495},"    computed",[235,21634,5182],{"class":499},[235,21636,21637,21640],{"class":237,"line":3605},[235,21638,21639],{"class":495},"        max",[235,21641,21642],{"class":499},"(){\n",[235,21644,21645,21647,21649,21651,21653,21655,21658,21661,21663,21665,21667,21669,21671,21674,21676],{"class":237,"line":3611},[235,21646,19649],{"class":1269},[235,21648,9924],{"class":519},[235,21650,1694],{"class":499},[235,21652,21366],{"class":252},[235,21654,21369],{"class":495},[235,21656,21657],{"class":499},"this.",[235,21659,21660],{"class":519},"$route",[235,21662,1694],{"class":499},[235,21664,20022],{"class":519},[235,21666,1694],{"class":499},[235,21668,9785],{"class":519},[235,21670,4040],{"class":499},[235,21672,21673],{"class":2836}," 15",[235,21675,1715],{"class":495},[235,21677,1348],{"class":499},[235,21679,21680],{"class":237,"line":3616},[235,21681,5276],{"class":499},[235,21683,21684,21687],{"class":237,"line":3621},[235,21685,21686],{"class":495},"        num",[235,21688,21642],{"class":499},[235,21690,21691,21694,21697,21699,21701],{"class":237,"line":3626},[235,21692,21693],{"class":1375},"            let",[235,21695,21696],{"class":519}," tmp",[235,21698,4116],{"class":499},[235,21700,9370],{"class":495},[235,21702,1348],{"class":499},[235,21704,21705,21708,21710,21712,21715,21717,21719,21721,21723,21726,21729,21731,21734,21737,21739],{"class":237,"line":3632},[235,21706,21707],{"class":1269},"            for",[235,21709,1705],{"class":495},[235,21711,4008],{"class":1375},[235,21713,21714],{"class":519}," n",[235,21716,1382],{"class":499},[235,21718,4576],{"class":2836},[235,21720,13931],{"class":499},[235,21722,21714],{"class":519},[235,21724,21725],{"class":499},"\u003C=this.",[235,21727,21728],{"class":519},"max",[235,21730,13931],{"class":499},[235,21732,21733],{"class":519},"n",[235,21735,21736],{"class":499},"++",[235,21738,1715],{"class":495},[235,21740,1976],{"class":499},[235,21742,21743,21746,21748,21750,21753,21755,21758,21760,21762,21765,21767,21769],{"class":237,"line":7238},[235,21744,21745],{"class":1269},"                if",[235,21747,1705],{"class":495},[235,21749,21733],{"class":519},[235,21751,21752],{"class":499}," ==",[235,21754,8648],{"class":2836},[235,21756,21757],{"class":499}," ||",[235,21759,21714],{"class":519},[235,21761,21752],{"class":499},[235,21763,21764],{"class":499}," this.",[235,21766,21728],{"class":519},[235,21768,1715],{"class":495},[235,21770,1976],{"class":499},[235,21772,21773,21776,21778,21780,21782,21784,21787,21789,21791,21793,21796,21798,21800,21802,21804],{"class":237,"line":7244},[235,21774,21775],{"class":519},"                    tmp",[235,21777,1694],{"class":499},[235,21779,4606],{"class":252},[235,21781,1705],{"class":495},[235,21783,1930],{"class":499},[235,21785,21786],{"class":495},"pg",[235,21788,500],{"class":499},[235,21790,186],{"class":4702},[235,21792,1404],{"class":499},[235,21794,21795],{"class":495},"num",[235,21797,500],{"class":499},[235,21799,21733],{"class":519},[235,21801,1950],{"class":499},[235,21803,1715],{"class":495},[235,21805,1348],{"class":499},[235,21807,21808,21811],{"class":237,"line":7249},[235,21809,21810],{"class":1269},"                    continue",[235,21812,1348],{"class":499},[235,21814,21815],{"class":237,"line":7259},[235,21816,15723],{"class":499},[235,21818,21819,21821,21824,21826,21828,21830,21833,21836,21838,21840,21843,21845,21847,21849,21851,21853,21855,21857,21859],{"class":237,"line":7274},[235,21820,21745],{"class":1269},[235,21822,21823],{"class":495},"((",[235,21825,21657],{"class":499},[235,21827,21357],{"class":519},[235,21829,10576],{"class":499},[235,21831,21832],{"class":2836}," 2",[235,21834,21835],{"class":499}," \u003C=",[235,21837,21714],{"class":519},[235,21839,10622],{"class":495},[235,21841,21842],{"class":499},"&&",[235,21844,10342],{"class":495},[235,21846,21733],{"class":519},[235,21848,21835],{"class":499},[235,21850,21764],{"class":499},[235,21852,21357],{"class":519},[235,21854,10587],{"class":499},[235,21856,21832],{"class":2836},[235,21858,10235],{"class":495},[235,21860,1976],{"class":499},[235,21862,21863,21865,21867,21869,21871,21873,21875,21877,21879,21881,21883,21885,21887,21889],{"class":237,"line":7279},[235,21864,21775],{"class":519},[235,21866,1694],{"class":499},[235,21868,4606],{"class":252},[235,21870,1705],{"class":495},[235,21872,1930],{"class":499},[235,21874,21786],{"class":495},[235,21876,500],{"class":499},[235,21878,186],{"class":4702},[235,21880,1404],{"class":499},[235,21882,21795],{"class":495},[235,21884,500],{"class":499},[235,21886,21733],{"class":519},[235,21888,1950],{"class":499},[235,21890,1953],{"class":495},[235,21892,21893,21895],{"class":237,"line":7284},[235,21894,21810],{"class":1269},[235,21896,1348],{"class":499},[235,21898,21899],{"class":237,"line":7289},[235,21900,15723],{"class":499},[235,21902,21903,21905,21907,21909,21911,21913,21915,21917,21919,21921,21923,21925,21928,21930,21932,21934,21936,21938,21940,21942,21944,21946,21949],{"class":237,"line":7294},[235,21904,21745],{"class":1269},[235,21906,21823],{"class":495},[235,21908,21657],{"class":499},[235,21910,21357],{"class":519},[235,21912,10576],{"class":499},[235,21914,21832],{"class":2836},[235,21916,10576],{"class":499},[235,21918,8648],{"class":2836},[235,21920,21752],{"class":499},[235,21922,21714],{"class":519},[235,21924,10622],{"class":495},[235,21926,21927],{"class":499},"||",[235,21929,10342],{"class":495},[235,21931,21733],{"class":519},[235,21933,21752],{"class":499},[235,21935,21764],{"class":499},[235,21937,21357],{"class":519},[235,21939,10587],{"class":499},[235,21941,21832],{"class":2836},[235,21943,10587],{"class":499},[235,21945,8648],{"class":2836},[235,21947,21948],{"class":495},") )",[235,21950,1976],{"class":499},[235,21952,21953,21956,21958,21960,21962,21964,21966,21968,21971,21973,21975,21977,21979,21982,21984,21986],{"class":237,"line":7299},[235,21954,21955],{"class":519},"                   tmp",[235,21957,1694],{"class":499},[235,21959,4606],{"class":252},[235,21961,1705],{"class":495},[235,21963,1930],{"class":499},[235,21965,21786],{"class":495},[235,21967,500],{"class":499},[235,21969,21970],{"class":4702},"false",[235,21972,1404],{"class":499},[235,21974,21795],{"class":495},[235,21976,500],{"class":499},[235,21978,1517],{"class":499},[235,21980,21981],{"class":245},"...",[235,21983,1517],{"class":499},[235,21985,1950],{"class":499},[235,21987,1953],{"class":495},[235,21989,21990,21992],{"class":237,"line":7310},[235,21991,21810],{"class":1269},[235,21993,1348],{"class":499},[235,21995,21996],{"class":237,"line":7331},[235,21997,15723],{"class":499},[235,21999,22000],{"class":237,"line":7336},[235,22001,5812],{"class":499},[235,22003,22004,22006,22008],{"class":237,"line":7356},[235,22005,19649],{"class":1269},[235,22007,21696],{"class":519},[235,22009,1348],{"class":499},[235,22011,22012],{"class":237,"line":7361},[235,22013,4086],{"class":499},[235,22015,22016],{"class":237,"line":7370},[235,22017,4091],{"class":499},[235,22019,22020],{"class":237,"line":7379},[235,22021,1317],{"class":499},[235,22023,22024,22026,22028],{"class":237,"line":7384},[235,22025,1530],{"class":499},[235,22027,1558],{"class":495},[235,22029,1487],{"class":499},[13,22031,22032],{},"詳細を解説します。",[81,22034,22036],{"id":22035},"idの値とページ数をチェック","{id}の値とページ数をチェック",[13,22038,22039,22042,22043,22046,22047,22050,22051,6554,22054,22056],{},[39,22040,22041],{},"\u002Farciles\u002Fpage\u002F{id}","において",[39,22044,22045],{},"{id}","が数値のみ許可するようにします。そこでNuxt SSRでは",[39,22048,22049],{},"validate()","というものを使用できます。",[39,22052,22053],{},"params.id",[39,22055,22045],{},"の値が取得できますので、そこで数値であることを確認します。もしそうでなければ、１ページ目にリダイレクトさせます。",[13,22058,22059],{},"数値であっても提供するページを超えた数を指定されては困ります。その時のために{id}のページ数が存在するかをチェックしておきます。もし存在しなければ１ページ目にリダイレクトさせます。",[226,22061,22063],{"className":3990,"code":22062,"language":3992,"meta":231,"style":231},"if(current > Math.ceil( count.length \u002F store.state.indexPerPage)) redirect('\u002Farticles');\n",[39,22064,22065],{"__ignoreMap":231},[235,22066,22067,22069,22072,22074,22076,22078,22080,22083,22085,22088,22090,22092,22094,22096,22098,22101,22103,22105,22107,22109,22111,22113],{"class":237,"line":238},[235,22068,7106],{"class":1269},[235,22070,22071],{"class":519},"(current ",[235,22073,1524],{"class":499},[235,22075,9924],{"class":519},[235,22077,1694],{"class":499},[235,22079,21366],{"class":252},[235,22081,22082],{"class":519},"( count",[235,22084,1694],{"class":499},[235,22086,22087],{"class":519},"length ",[235,22089,4055],{"class":499},[235,22091,19940],{"class":519},[235,22093,1694],{"class":499},[235,22095,19571],{"class":519},[235,22097,1694],{"class":499},[235,22099,22100],{"class":519},"indexPerPage)) ",[235,22102,21393],{"class":252},[235,22104,1705],{"class":519},[235,22106,1345],{"class":499},[235,22108,21257],{"class":245},[235,22110,1345],{"class":499},[235,22112,1715],{"class":519},[235,22114,1348],{"class":499},[1225,22116,22119],{"className":22117},[1228,22118],"alert-warning","\nSSRであれば上記の設定は必須ですが、静的書き出しでは正直入りません。なぜなら静的書き出し時にはこのページング分だけのルートしか提供されないためです。静的HTMLで提供する時は存在しないルートにアクセスした時、404のページにリダイレクトさせておくといいです。\n",[81,22121,22122],{"id":22122},"ページングに必要な値を取得する",[13,22124,22125],{},"これはページングを実装するために必要なロジックのな話になるので、一部省略しますが必要な値は",[17,22127,22128,22131],{},[20,22129,22130],{},"何件目から(from)",[20,22132,22133],{},"何件目まで(to)",[13,22135,22136],{},"が必要となります。ソースでは以下のように使用しています。",[226,22138,22140],{"className":3990,"code":22139,"language":3992,"meta":231,"style":231},"const from = store.state.indexPerPage * (params.id - 1);     \u002F\u002F何件目から\nconst to = store.state.indexPerPage * params.id;             \u002F\u002F何件目まで\n\nconst content = await $content('articles')\n.only(['title','path'])\n.sortBy('createdAt', 'desc')\n.skip(from).limit(to)   \u002F\u002F ページング取得\n.fetch();\n",[39,22141,22142,22183,22215,22219,22242,22266,22290,22309],{"__ignoreMap":231},[235,22143,22144,22146,22149,22151,22153,22155,22157,22159,22162,22164,22167,22169,22172,22174,22176,22178,22180],{"class":237,"line":238},[235,22145,1376],{"class":1375},[235,22147,22148],{"class":519}," from ",[235,22150,1382],{"class":499},[235,22152,19940],{"class":519},[235,22154,1694],{"class":499},[235,22156,19571],{"class":519},[235,22158,1694],{"class":499},[235,22160,22161],{"class":519},"indexPerPage ",[235,22163,8184],{"class":499},[235,22165,22166],{"class":519}," (params",[235,22168,1694],{"class":499},[235,22170,22171],{"class":519},"id ",[235,22173,4573],{"class":499},[235,22175,8648],{"class":2836},[235,22177,1715],{"class":519},[235,22179,13931],{"class":499},[235,22181,22182],{"class":3119},"     \u002F\u002F何件目から\n",[235,22184,22185,22187,22190,22192,22194,22196,22198,22200,22202,22204,22206,22208,22210,22212],{"class":237,"line":249},[235,22186,1376],{"class":1375},[235,22188,22189],{"class":519}," to ",[235,22191,1382],{"class":499},[235,22193,19940],{"class":519},[235,22195,1694],{"class":499},[235,22197,19571],{"class":519},[235,22199,1694],{"class":499},[235,22201,22161],{"class":519},[235,22203,8184],{"class":499},[235,22205,19950],{"class":519},[235,22207,1694],{"class":499},[235,22209,9785],{"class":519},[235,22211,13931],{"class":499},[235,22213,22214],{"class":3119},"             \u002F\u002F何件目まで\n",[235,22216,22217],{"class":237,"line":259},[235,22218,263],{"emptyLinePlaceholder":262},[235,22220,22221,22223,22226,22228,22230,22232,22234,22236,22238,22240],{"class":237,"line":266},[235,22222,1376],{"class":1375},[235,22224,22225],{"class":519}," content ",[235,22227,1382],{"class":499},[235,22229,19968],{"class":1269},[235,22231,19971],{"class":252},[235,22233,1705],{"class":519},[235,22235,1345],{"class":499},[235,22237,20452],{"class":245},[235,22239,1345],{"class":499},[235,22241,1953],{"class":519},[235,22243,22244,22246,22248,22250,22252,22254,22256,22258,22260,22262,22264],{"class":237,"line":275},[235,22245,1694],{"class":499},[235,22247,19991],{"class":252},[235,22249,20081],{"class":519},[235,22251,1345],{"class":499},[235,22253,9125],{"class":245},[235,22255,1345],{"class":499},[235,22257,1404],{"class":499},[235,22259,1345],{"class":499},[235,22261,2098],{"class":245},[235,22263,1345],{"class":499},[235,22265,20155],{"class":519},[235,22267,22268,22270,22272,22274,22276,22278,22280,22282,22284,22286,22288],{"class":237,"line":283},[235,22269,1694],{"class":499},[235,22271,20162],{"class":252},[235,22273,1705],{"class":519},[235,22275,1345],{"class":499},[235,22277,20169],{"class":245},[235,22279,1345],{"class":499},[235,22281,1404],{"class":499},[235,22283,503],{"class":499},[235,22285,20178],{"class":245},[235,22287,1345],{"class":499},[235,22289,1953],{"class":519},[235,22291,22292,22294,22296,22299,22301,22303,22306],{"class":237,"line":291},[235,22293,1694],{"class":499},[235,22295,20220],{"class":252},[235,22297,22298],{"class":519},"(from)",[235,22300,1694],{"class":499},[235,22302,20231],{"class":252},[235,22304,22305],{"class":519},"(to)   ",[235,22307,22308],{"class":3119},"\u002F\u002F ページング取得\n",[235,22310,22311,22313,22315,22317],{"class":237,"line":298},[235,22312,1694],{"class":499},[235,22314,20036],{"class":252},[235,22316,2224],{"class":519},[235,22318,1348],{"class":499},[13,22320,22321,22323],{},[39,22322,22053],{},"が現在のページ数となっていますので、それを参考にしてページングによるコンテンツ取得をします。",[81,22325,22326],{"id":22326},"最大ページと表示ページ範囲を設定してレンダーする",[13,22328,22329,22331],{},[39,22330,20818],{},"での設定は以上でOKです。params.idから現在ページ数を用いてページングのレンダーを構築します。私のページングでは",[17,22333,22334,22337,22340],{},[20,22335,22336],{},"１ページ目と最後のページは常に表示",[20,22338,22339],{},"現在ページから2ページ分だけ表示",[20,22341,22342],{},"範囲外のページは「...」で表示する",[13,22344,22345],{},"という仕様で実装されています。詳細な仕組みは上記のソースをみてください。必要分のページのリンクを作成してページングは完成です。",[74,22347,22349],{"id":22348},"静的書き出しの際には特に気にせず大丈夫","静的書き出しの際には特に気にせず大丈夫。",[13,22351,22352,22353,22356,22357,22359],{},"ページングの設定して次は静的書き出しを行います。ただし前回のようにルートをnuxtに伝えるということは不要です。どうやら",[39,22354,22355],{},"\u002Farticles\u002Findex","を書き出す時にページングの",[39,22358,20320],{},"を辿ってルートを解決してくれているそうです。実際の書き出しでも",[226,22361,22364],{"className":22362,"code":22363,"language":934},[932],"✔ Generated route \"\u002Farticles\u002Fpage\n✔ Generated route \"\u002Farticles\u002Fpage\u002F1\" \n✔ Generated route \"\u002Farticles\u002Fpage\u002F2\" \n",[39,22365,22363],{"__ignoreMap":231},[13,22367,22368],{},"以上のようなログが確認できました。",[74,22370,2393],{"id":2393},[13,22372,22373],{},"以上で一覧ページの作成とページングが実装終了しました。ページングとページリストはコンポーネント化しておいた方が後々の開発が楽になります。次回はカテゴリーとタグ機能の解説を行います。",[2399,22375,22376],{},"html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sbqyR, html code.shiki .sbqyR{--shiki-default:#FF9CAC}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}",{"title":231,"searchDepth":259,"depth":259,"links":22378},[22379,22383,22388,22389],{"id":20400,"depth":249,"text":20400,"children":22380},[22381,22382],{"id":20403,"depth":259,"text":20403},{"id":20444,"depth":259,"text":20444},{"id":20849,"depth":249,"text":20849,"children":22384},[22385,22386,22387],{"id":22035,"depth":259,"text":22036},{"id":22122,"depth":259,"text":22122},{"id":22326,"depth":259,"text":22326},{"id":22348,"depth":249,"text":22349},{"id":2393,"depth":249,"text":2393},[2427],"2021-05-06","Nuxt Content × SSG で作る静的ブログ。記事一覧ページとページング機能ついて説明。",{},"\u002Fseries\u002Fnuxt-content-blog-3",{"title":20378,"description":22392},"series\u002Fnuxt-content-blog-3",[1262,18699],"A6PomFr-zdk_yRRjUN1XT-Qhy330_OwrjwFmZaj63C8",{"id":22400,"title":22401,"body":22402,"category":24068,"createdAt":24069,"description":24070,"extension":2430,"index":249,"meta":24071,"navigation":262,"path":24072,"publish":262,"seo":24073,"series":20370,"seriesTitle":20371,"stem":24074,"tag":24075,"thumbnail":20374,"updatedAt":2439,"__hash__":24076},"series\u002Fseries\u002Fnuxt-content-blog-2.md","Nuxt Content × SSG で作る静的ブログ。２：基本的な記事項目のレンダリングと静的書き出し",{"type":10,"value":22403,"toc":24052},[22404,22410,22421,22423,22426,22429,22441,22452,22458,22475,22479,22485,22490,22511,22515,22521,22653,22667,22672,22689,22692,22700,22703,22706,22717,22728,22775,22788,22791,23030,23037,23054,23061,23065,23068,23088,23092,23095,23098,23104,23110,23167,23170,23173,23184,23190,23193,23196,23199,23787,23790,23805,23969,23985,23988,23993,23999,24006,24012,24018,24024,24033,24036,24049],[13,22405,18614,22406,22409],{},[197,22407,18618],{"href":22408},"\u002Fseries\u002Fnuxt-content-blog\u002F1","は概念と基本的なコンテンツの作成・取得・表示について解説しました。今回の記事では",[17,22411,22412,22415,22418],{},[20,22413,22414],{},"nuxt.jsにおけるpage構成の設定",[20,22416,22417],{},"目次生成、画像のレンダリング、どんな項目をレンダリングできるのか？",[20,22419,22420],{},"静的書き出しの設定",[13,22422,20397],{},[74,22424,22425],{"id":22425},"サイトのルーティングを考えてpagesの構成を設定する",[81,22427,22428],{"id":22428},"何をどう設定すればいいか",[13,22430,22431,22432,22434,22435,22437,22438,22440],{},"Nuxt.jsは",[39,22433,19889],{},"というディレクトリ配下にファイルを作ることで、vue-routerの設定が自動で行われURLが生成されます。私のブログでは",[39,22436,20417],{},"というURLで対象の記事を呼び出します。そのURLが有効になるには",[39,22439,19889],{},"ディレクトリの構築をする必要があります。",[13,22442,22443,22444,22447,22448,22451],{},"一方、Nuxt Contentで任意の記事データを取得してみると",[39,22445,22446],{},"path:","というプロパティがあります。それは",[39,22449,22450],{},"content\u002F","ディレクトリをルートとしたパスになっています。以下のような構成の場合、",[226,22453,22456],{"className":22454,"code":22455,"language":934},[932],"├── content\n│   ├── articles\n│   │   ├── aaaaaa.md\n",[39,22457,22455],{"__ignoreMap":231},[13,22459,22460,22463,22464,22467,22468,22471,22472,22474],{},[39,22461,22462],{},"aaaaaa.md","のデータのパスは",[39,22465,22466],{},"\u002Farticles\u002Faaaaaa","となります。つまり",[39,22469,22470],{},"https:\u002F\u002Fexample.com\u002Farticles\u002Faaaaaa","というルートに対して、",[39,22473,22462],{},"が呼び出されるように設定します。",[81,22476,22478],{"id":22477},"ひとまず以下のようにpageを作成","ひとまず以下のようにpage\u002Fを作成",[13,22480,22481,22482,22484],{},"ひとまず以下のように",[39,22483,19889],{},"配下に作成してください。",[226,22486,22488],{"className":22487,"code":20410,"language":934},[932],[39,22489,20410],{"__ignoreMap":231},[13,22491,22492,22495,22496,13843,22501,22503,22504,6554,22507,22510],{},[39,22493,22494],{},"_slug.vue","といものを作ることで",[197,22497,22500],{"href":22498,"rel":22499},"https:\u002F\u002Fja.nuxtjs.org\u002Fdocs\u002F2.x\u002Fdirectory-structure\u002Fpages",[201],"公式にある通り",[39,22502,20417],{},"のルートに対して",[39,22505,22506],{},"params.sulg",[39,22508,22509],{},"{sulg}","の値を取得できるようになります。",[81,22512,22514],{"id":22513},"paramssulgで指定されたsulgのファイルfetchする","params.sulgで指定されたsulgのファイルfetchする",[13,22516,1243,22517,22520],{},[39,22518,22519],{},"_sulg.vue","で以下のように記述します。",[226,22522,22525],{"className":1472,"code":22523,"filename":22524,"language":1208,"meta":231,"style":231},"\u003Ctemplate>\n  \u003Carticle>\n    \u003Cnuxt-content :document=\"content\" \u002F>\n  \u003C\u002Farticle>\n\u003C\u002Ftemplate>\n\u003Cscirpt>\nexport default {\n  async asyncData({ $content, params,redirect }) {\n    const content = await $content('articles').where({path:\"\u002Farticles\u002F\"+params.slug}).fetch();\n    if(content.length > 0){\n      return {\n        content:content[0],\n      }\n    }else{\n      redirect('\u002Farticles')\n    }\n  }\n}\n\u003C\u002Fscript>\n\n","\u002Farticles\u002F_sulg.vue",[39,22526,22527,22535,22545,22566,22575,22583,22592,22597,22602,22607,22612,22617,22622,22626,22631,22636,22640,22644,22648],{"__ignoreMap":231},[235,22528,22529,22531,22533],{"class":237,"line":238},[235,22530,1481],{"class":499},[235,22532,1484],{"class":495},[235,22534,1487],{"class":499},[235,22536,22537,22540,22543],{"class":237,"line":249},[235,22538,22539],{"class":499},"  \u003C",[235,22541,22542],{"class":495},"article",[235,22544,1487],{"class":499},[235,22546,22547,22549,22552,22555,22557,22559,22561,22563],{"class":237,"line":259},[235,22548,1492],{"class":499},[235,22550,22551],{"class":495},"nuxt-content",[235,22553,22554],{"class":1375}," :document",[235,22556,1382],{"class":499},[235,22558,1517],{"class":499},[235,22560,12519],{"class":245},[235,22562,1517],{"class":499},[235,22564,22565],{"class":499}," \u002F>\n",[235,22567,22568,22571,22573],{"class":237,"line":266},[235,22569,22570],{"class":499},"  \u003C\u002F",[235,22572,22542],{"class":495},[235,22574,1487],{"class":499},[235,22576,22577,22579,22581],{"class":237,"line":275},[235,22578,1530],{"class":499},[235,22580,1484],{"class":495},[235,22582,1487],{"class":499},[235,22584,22585,22587,22590],{"class":237,"line":283},[235,22586,1481],{"class":499},[235,22588,22589],{"class":495},"scirpt",[235,22591,1487],{"class":499},[235,22593,22594],{"class":237,"line":291},[235,22595,22596],{"class":519},"export default {\n",[235,22598,22599],{"class":237,"line":298},[235,22600,22601],{"class":519},"  async asyncData({ $content, params,redirect }) {\n",[235,22603,22604],{"class":237,"line":380},[235,22605,22606],{"class":519},"    const content = await $content('articles').where({path:\"\u002Farticles\u002F\"+params.slug}).fetch();\n",[235,22608,22609],{"class":237,"line":465},[235,22610,22611],{"class":519},"    if(content.length > 0){\n",[235,22613,22614],{"class":237,"line":590},[235,22615,22616],{"class":519},"      return {\n",[235,22618,22619],{"class":237,"line":604},[235,22620,22621],{"class":519},"        content:content[0],\n",[235,22623,22624],{"class":237,"line":612},[235,22625,2176],{"class":519},[235,22627,22628],{"class":237,"line":623},[235,22629,22630],{"class":519},"    }else{\n",[235,22632,22633],{"class":237,"line":634},[235,22634,22635],{"class":519},"      redirect('\u002Farticles')\n",[235,22637,22638],{"class":237,"line":641},[235,22639,2181],{"class":519},[235,22641,22642],{"class":237,"line":653},[235,22643,12914],{"class":519},[235,22645,22646],{"class":237,"line":661},[235,22647,1317],{"class":519},[235,22649,22650],{"class":237,"line":670},[235,22651,22652],{"class":519},"\u003C\u002Fscript>\n",[13,22654,22655,22657,22658,22660,22661,6554,22663,22666],{},[39,22656,20818],{},"中で",[39,22659,20825],{},"をフェッチします。そして",[39,22662,20344],{},[39,22664,22665],{},"\"\u002Farticles\u002F\"+params.slug","に一致するコンテンツを引っ張るようにします。",[13,22668,22669,22671],{},[39,22670,20006],{},"クエリを使用すると配列で結果が返るので、あれば一致した結果、なければ一覧ページにリダイレクトするようにします。以上でNuxtにおけるpagesディレクトリの設定は完了です。",[1225,22673,22675,22677,22678,22681,22682,22684,22685],{"className":22674},[1228,2914],[39,22676,20818],{},"はSSRの時の",[39,22679,22680],{},"page\u002F","配下のファイルで使用できます。サーバーサイドで処理される箇所であり、そこで$contentをfetchします。静的書き出しを行うと、",[39,22683,20818],{},"内の処理は書き出し中に実行されます。\n",[197,22686,22688],{"href":22687,"target":2918},"https:\u002F\u002Fnuxtjs.org\u002Fdocs\u002F2.x\u002Ffeatures\u002Fdata-fetching","公式：Data Fetching",[74,22690,22691],{"id":22691},"コンテンツの作成",[13,22693,22694,22695,22699],{},"ブログ記事は単に文章だけでなく、太字、リンク、画像、見出し、目次が大体必要になります。文章の修飾はマークダウンの記述を行えば問題ありません。マークダウン記法は今回は解説しません。",[197,22696,202],{"href":22697,"rel":22698},"https:\u002F\u002Fqiita.com\u002Fkamorits\u002Fitems\u002F6f342da395ad57468ae3",[201],"がお世話になりました。",[81,22701,22702],{"id":22702},"画像をレンダリングする場合",[13,22704,22705],{},"マークダウンで画像を表示する場合は基本的に以下のように記述します。",[226,22707,22711],{"className":22708,"code":22709,"language":22710,"meta":231,"style":231},"language-markdown shiki shiki-themes material-theme-ocean","![image alt text](\u002Fimage\u002Fsample.jpg)\n","markdown",[39,22712,22713],{"__ignoreMap":231},[235,22714,22715],{"class":237,"line":238},[235,22716,22709],{},[13,22718,22719,22720,22723,22724,22727],{},"Nuxtの場合は画像を",[39,22721,22722],{},"asset","あたりに入れておき、",[39,22725,22726],{},"require('~\u002Fasset\u002Fsample.jpg')","という感じで依存性を解決できます。しかしマークダウンでは以下のパターンで画像パスの解決ができません。",[226,22729,22731],{"className":22708,"code":22730,"language":22710,"meta":231,"style":231},"\n\u002F\u002F パターン１\n![image alt text](~\u002Fasset\u002Fsample.jpg)\n\n\u002F\u002F パターン２\n![image alt text](\u002Fasset\u002Fsample.jpg)\n\n\u002F\u002F パターン３\n![image alt text](require(~\u002Fasset\u002Fsample.jpg))\n\n",[39,22732,22733,22737,22742,22747,22751,22756,22761,22765,22770],{"__ignoreMap":231},[235,22734,22735],{"class":237,"line":238},[235,22736,263],{"emptyLinePlaceholder":262},[235,22738,22739],{"class":237,"line":249},[235,22740,22741],{},"\u002F\u002F パターン１\n",[235,22743,22744],{"class":237,"line":259},[235,22745,22746],{},"![image alt text](~\u002Fasset\u002Fsample.jpg)\n",[235,22748,22749],{"class":237,"line":266},[235,22750,263],{"emptyLinePlaceholder":262},[235,22752,22753],{"class":237,"line":275},[235,22754,22755],{},"\u002F\u002F パターン２\n",[235,22757,22758],{"class":237,"line":283},[235,22759,22760],{},"![image alt text](\u002Fasset\u002Fsample.jpg)\n",[235,22762,22763],{"class":237,"line":291},[235,22764,263],{"emptyLinePlaceholder":262},[235,22766,22767],{"class":237,"line":298},[235,22768,22769],{},"\u002F\u002F パターン３\n",[235,22771,22772],{"class":237,"line":380},[235,22773,22774],{},"![image alt text](require(~\u002Fasset\u002Fsample.jpg))\n",[13,22776,22777,22778,22781,22782,22787],{},"画像のレンダリングは",[39,22779,22780],{},"\"@nuxt\u002Fcontent\": \"^1.14.0\"","時点で特段に対応されておらず、ドキュメントにも書かれていませんでした。",[197,22783,22786],{"href":22784,"rel":22785},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fcontent\u002Fissues\u002F106",[201],"Githubのissueでも報告されているよう","に議論となっています。",[13,22789,22790],{},"一応解決策としてはマークダウンファイルそのものにVueコンポーネントを書いてしまうことです。最初に画像レンダリング用のコンポーネントを作成します。",[226,22792,22795],{"className":1472,"code":22793,"filename":22794,"language":1208,"meta":231,"style":231},"\u003Ctemplate>\n  \u003Cimg :src=\"imgSrc()\" :alt=\"alt\"\u002F>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\nexport default {\n  props: {\n    src: {\n      type: String,\n      required: true\n    },\n    alt: {\n      type: String,\n    },\n  },\n  methods: {\n    imgSrc() {\n      try {\n        return require(`~\u002Fassets\u002Fimage\u002F${this.src}`)\n      } catch (error) {\n        return null\n      }\n    }\n  },\n}\n\u003C\u002Fscript>\n","components\u002FimageRender.vue",[39,22796,22797,22805,22837,22845,22849,22857,22865,22874,22883,22895,22904,22908,22917,22927,22931,22935,22944,22953,22960,22983,22999,23006,23010,23014,23018,23022],{"__ignoreMap":231},[235,22798,22799,22801,22803],{"class":237,"line":238},[235,22800,1481],{"class":499},[235,22802,1484],{"class":495},[235,22804,1487],{"class":499},[235,22806,22807,22809,22811,22814,22816,22818,22821,22823,22826,22828,22830,22833,22835],{"class":237,"line":249},[235,22808,22539],{"class":499},[235,22810,5066],{"class":495},[235,22812,22813],{"class":1375}," :src",[235,22815,1382],{"class":499},[235,22817,1517],{"class":499},[235,22819,22820],{"class":245},"imgSrc()",[235,22822,1517],{"class":499},[235,22824,22825],{"class":1375}," :alt",[235,22827,1382],{"class":499},[235,22829,1517],{"class":499},[235,22831,22832],{"class":245},"alt",[235,22834,1517],{"class":499},[235,22836,5081],{"class":499},[235,22838,22839,22841,22843],{"class":237,"line":259},[235,22840,1530],{"class":499},[235,22842,1484],{"class":495},[235,22844,1487],{"class":499},[235,22846,22847],{"class":237,"line":266},[235,22848,263],{"emptyLinePlaceholder":262},[235,22850,22851,22853,22855],{"class":237,"line":275},[235,22852,1481],{"class":499},[235,22854,1558],{"class":495},[235,22856,1487],{"class":499},[235,22858,22859,22861,22863],{"class":237,"line":283},[235,22860,1270],{"class":1269},[235,22862,1273],{"class":1269},[235,22864,1276],{"class":499},[235,22866,22867,22870,22872],{"class":237,"line":291},[235,22868,22869],{"class":495},"  props",[235,22871,500],{"class":499},[235,22873,1276],{"class":499},[235,22875,22876,22879,22881],{"class":237,"line":298},[235,22877,22878],{"class":495},"    src",[235,22880,500],{"class":499},[235,22882,1276],{"class":499},[235,22884,22885,22888,22890,22893],{"class":237,"line":380},[235,22886,22887],{"class":495},"      type",[235,22889,500],{"class":499},[235,22891,22892],{"class":519}," String",[235,22894,1984],{"class":499},[235,22896,22897,22900,22902],{"class":237,"line":465},[235,22898,22899],{"class":495},"      required",[235,22901,500],{"class":499},[235,22903,18740],{"class":4702},[235,22905,22906],{"class":237,"line":590},[235,22907,4091],{"class":499},[235,22909,22910,22913,22915],{"class":237,"line":604},[235,22911,22912],{"class":495},"    alt",[235,22914,500],{"class":499},[235,22916,1276],{"class":499},[235,22918,22919,22921,22923,22925],{"class":237,"line":612},[235,22920,22887],{"class":495},[235,22922,500],{"class":499},[235,22924,22892],{"class":519},[235,22926,1984],{"class":499},[235,22928,22929],{"class":237,"line":623},[235,22930,4091],{"class":499},[235,22932,22933],{"class":237,"line":634},[235,22934,12852],{"class":499},[235,22936,22937,22940,22942],{"class":237,"line":641},[235,22938,22939],{"class":495},"  methods",[235,22941,500],{"class":499},[235,22943,1276],{"class":499},[235,22945,22946,22949,22951],{"class":237,"line":653},[235,22947,22948],{"class":495},"    imgSrc",[235,22950,2224],{"class":499},[235,22952,1276],{"class":499},[235,22954,22955,22958],{"class":237,"line":661},[235,22956,22957],{"class":1269},"      try",[235,22959,1276],{"class":499},[235,22961,22962,22964,22966,22968,22970,22973,22975,22977,22979,22981],{"class":237,"line":670},[235,22963,19579],{"class":1269},[235,22965,1702],{"class":252},[235,22967,1705],{"class":495},[235,22969,7552],{"class":499},[235,22971,22972],{"class":245},"~\u002Fassets\u002Fimage\u002F",[235,22974,4657],{"class":499},[235,22976,21657],{"class":499},[235,22978,3925],{"class":519},[235,22980,4663],{"class":499},[235,22982,1953],{"class":495},[235,22984,22985,22987,22990,22992,22995,22997],{"class":237,"line":678},[235,22986,4708],{"class":499},[235,22988,22989],{"class":1269}," catch",[235,22991,10342],{"class":495},[235,22993,22994],{"class":519},"error",[235,22996,10622],{"class":495},[235,22998,1976],{"class":499},[235,23000,23001,23003],{"class":237,"line":686},[235,23002,19579],{"class":1269},[235,23004,23005],{"class":499}," null\n",[235,23007,23008],{"class":237,"line":694},[235,23009,2176],{"class":499},[235,23011,23012],{"class":237,"line":702},[235,23013,2181],{"class":499},[235,23015,23016],{"class":237,"line":712},[235,23017,12852],{"class":499},[235,23019,23020],{"class":237,"line":723},[235,23021,1317],{"class":499},[235,23023,23024,23026,23028],{"class":237,"line":730},[235,23025,1530],{"class":499},[235,23027,1558],{"class":495},[235,23029,1487],{"class":499},[13,23031,23032,23033,23036],{},"上記のコンポーネントを ",[3700,23034,23035],{},"マークダウン"," に記述します。",[226,23038,23042],{"className":23039,"code":23040,"language":23041,"meta":231,"style":231},"language-sample.md shiki shiki-themes material-theme-ocean","以下のようにします。\n\u003CimageRender src=\"sample.jpg\"\u002F>\n","sample.md",[39,23043,23044,23049],{"__ignoreMap":231},[235,23045,23046],{"class":237,"line":238},[235,23047,23048],{},"以下のようにします。\n",[235,23050,23051],{"class":237,"line":249},[235,23052,23053],{},"\u003CimageRender src=\"sample.jpg\"\u002F>\n",[13,23055,23056,23057,23060],{},"上記の記述はNuxt Contentがåいい感じにvueコンポーネントとして扱ってくれます。パスの解決はコンポーネント内の",[39,23058,23059],{},"require()","が行います。あまりかっこいい方法ではありませんが、一応これで画像をレンダリングできます。",[81,23062,23064],{"id":23063},"html要素をレンダリングする","HTML要素をレンダリングする",[13,23066,23067],{},"Nuxt Contentはマークダウン内のHTMLをHTMLとして扱ってくれますので、カスタムな要素を記述できます。",[226,23069,23071],{"className":23039,"code":23070,"language":23041,"meta":231,"style":231},"\u003Cdiv class=\"alert alert-warning\">\nこのアラートもこのようにHTMLをマークダウンに書いています！\n\u003C\u002Fdiv>\n",[39,23072,23073,23078,23083],{"__ignoreMap":231},[235,23074,23075],{"class":237,"line":238},[235,23076,23077],{},"\u003Cdiv class=\"alert alert-warning\">\n",[235,23079,23080],{"class":237,"line":249},[235,23081,23082],{},"このアラートもこのようにHTMLをマークダウンに書いています！\n",[235,23084,23085],{"class":237,"line":259},[235,23086,23087],{},"\u003C\u002Fdiv>\n",[1225,23089,23091],{"className":23090},[1228,22118],"\nこのアラートもこのようにHTMLをマークダウンに書いています！\n",[81,23093,23094],{"id":23094},"シンタックスハイライトを有効にする",[13,23096,23097],{},"Nuxt Contentは一応開発者向けなのか、簡単にコードブロックに対してシンタックスハイライトを有効にすることができます。prismJSを使用するのでまずはインストールします。",[226,23099,23102],{"className":23100,"code":23101,"language":934},[932],"npm install prism-themes\n\n",[39,23103,23101],{"__ignoreMap":231},[13,23105,15584,23106,23109],{},[39,23107,23108],{},"nuxt.config.js","で以下のようにテーマのCSSを設定します。",[226,23111,23113],{"className":3990,"code":23112,"filename":23108,"language":3992,"meta":231,"style":231},"content: {\n    markdown: {\n      prism: {\n        theme: 'prism-themes\u002Fthemes\u002Fprism-material-oceanic.css'\n      }\n    }\n  },\n",[39,23114,23115,23123,23132,23141,23155,23159,23163],{"__ignoreMap":231},[235,23116,23117,23119,23121],{"class":237,"line":238},[235,23118,12519],{"class":241},[235,23120,500],{"class":499},[235,23122,1276],{"class":499},[235,23124,23125,23128,23130],{"class":237,"line":249},[235,23126,23127],{"class":241},"    markdown",[235,23129,500],{"class":499},[235,23131,1276],{"class":499},[235,23133,23134,23137,23139],{"class":237,"line":259},[235,23135,23136],{"class":241},"      prism",[235,23138,500],{"class":499},[235,23140,1276],{"class":499},[235,23142,23143,23146,23148,23150,23153],{"class":237,"line":266},[235,23144,23145],{"class":241},"        theme",[235,23147,500],{"class":499},[235,23149,503],{"class":499},[235,23151,23152],{"class":245},"prism-themes\u002Fthemes\u002Fprism-material-oceanic.css",[235,23154,509],{"class":499},[235,23156,23157],{"class":237,"line":275},[235,23158,2176],{"class":499},[235,23160,23161],{"class":237,"line":283},[235,23162,2181],{"class":499},[235,23164,23165],{"class":237,"line":291},[235,23166,12852],{"class":499},[13,23168,23169],{},"以上でコードブロック内にてシンタックスハイライトが有効になります。",[81,23171,23172],{"id":23172},"目次の作成",[13,23174,23175,23176,23179,23180,23183],{},"目次の作成、もとい見出しのデータの取得は簡単です。",[39,23177,23178],{},"const content = $content().fetch()","で取得した ",[39,23181,23182],{},"content.toc","で見出しのデータが取得できます。",[226,23185,23188],{"className":23186,"code":23187,"language":934},[932],"toc:Array[8]\n    0:Object\n        depth:2\n        id:\"サイトのルーティングを考えてpagesの構成を設定する\"\n        text:\"サイトのルーティングを考えてpagesの構成を設定する\"\n    1:Object\n",[39,23189,23187],{"__ignoreMap":231},[13,23191,23192],{},"私のブログの左サイドにある目次も、上記のようなオブジェクトを利用して作っています。",[81,23194,23195],{"id":23195},"その他の項目や要素について",[13,23197,23198],{},"以上がブログに必要であろう要素をNuxt Contentで記述しました。私の一般記事のtemplateは以下ようになっていますので、是非参考にしてください。",[226,23200,23203],{"className":1472,"code":23201,"filename":23202,"language":1208,"meta":231,"style":231},"\u003Ctemplate>\n  \u003Cdiv class=\"p-main-container\">\n    \u003Cdiv class=\"p-main-wrapper\">\n        \u002F\u002F目次のコンポーネント\n        \u003Ctoc :toc=\"content.toc\"\u002F>\n\n        \u002F\u002Fメインのエリア\n        \u003Cdiv id=\"l-center-area\">\n\n            \u002F\u002Fサムネイル\n            \u003Cimg v-if=\"thumbnail\" class=\"c-article-thumbnail\" :src=\"thumbnail\" :alt=\"content.title\">\n\n            \u002F\u002Fタグとカテゴリーのバッチ\n            \u003Cdiv class=\"p-article-badge p-badge-container\">\n                \u003Cnuxt-link class=\"c-tag-badge u-blue\" v-for=\"(c,index) in content.category\" :key=\"'category-'+index\" :to=\"'\u002Fcategory\u002F'+c\">\n                    \u003Cspan>{{$store.getters['getCategoryTextBySlug'](c)}}\u003C\u002Fspan>\n                \u003C\u002Fnuxt-link>\n                \u003Cnuxt-link class=\"c-tag-badge\" v-for=\"(t,index) in content.tag\" :key=\"'tag-'+index\" :to=\"'\u002Ftag\u002F'+t\">\n                    \u003Cspan>{{$store.getters['getTagTextBySlug'](t)}}\u003C\u002Fspan>\n                \u003C\u002Fnuxt-link>\n            \u003C\u002Fdiv>\n\n            \u003Ch1 class=\"c-article-header\">{{ content.title }}\u003C\u002Fh1>\n\n            \u002F\u002F 更新一時など\n            \u003Cdiv class=\"p-articler-date\">\n                \u003Cspan class=\"c-date\">\u003Cfa-icon :icon=\"['fa', 'history']\"\u002F>{{ updateAt }}\u003C\u002Fspan>\n                \u003Cspan class=\"c-date\">\u003Cfa-icon :icon=\"['far', 'clock']\"\u002F>{{ createdAt }}\u003C\u002Fspan>\n            \u003C\u002Fdiv>\n\n            \u002F\u002F マークダウンのレンダリング箇所\n            \u003Cnuxt-content :document=\"content\" \u002F>\n        \u003C\u002Fdiv>\n\n        \u002F\u002Fサイドメニュー\n        \u003Csidemenu\u002F>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n","pages\u002Farticles\u002F_slug.vue",[39,23204,23205,23213,23231,23250,23255,23275,23279,23284,23303,23307,23312,23362,23366,23371,23390,23442,23460,23468,23520,23537,23545,23553,23557,23585,23589,23594,23613,23660,23702,23710,23714,23719,23737,23745,23749,23754,23763,23771,23779],{"__ignoreMap":231},[235,23206,23207,23209,23211],{"class":237,"line":238},[235,23208,1481],{"class":499},[235,23210,1484],{"class":495},[235,23212,1487],{"class":499},[235,23214,23215,23217,23219,23221,23223,23225,23227,23229],{"class":237,"line":249},[235,23216,22539],{"class":499},[235,23218,1225],{"class":495},[235,23220,8005],{"class":1375},[235,23222,1382],{"class":499},[235,23224,1517],{"class":499},[235,23226,8291],{"class":245},[235,23228,1517],{"class":499},[235,23230,1487],{"class":499},[235,23232,23233,23235,23237,23239,23241,23243,23246,23248],{"class":237,"line":259},[235,23234,1492],{"class":499},[235,23236,1225],{"class":495},[235,23238,8005],{"class":1375},[235,23240,1382],{"class":499},[235,23242,1517],{"class":499},[235,23244,23245],{"class":245},"p-main-wrapper",[235,23247,1517],{"class":499},[235,23249,1487],{"class":499},[235,23251,23252],{"class":237,"line":266},[235,23253,23254],{"class":519},"        \u002F\u002F目次のコンポーネント\n",[235,23256,23257,23259,23262,23265,23267,23269,23271,23273],{"class":237,"line":275},[235,23258,1506],{"class":499},[235,23260,23261],{"class":495},"toc",[235,23263,23264],{"class":1375}," :toc",[235,23266,1382],{"class":499},[235,23268,1517],{"class":499},[235,23270,23182],{"class":245},[235,23272,1517],{"class":499},[235,23274,5081],{"class":499},[235,23276,23277],{"class":237,"line":283},[235,23278,263],{"emptyLinePlaceholder":262},[235,23280,23281],{"class":237,"line":291},[235,23282,23283],{"class":519},"        \u002F\u002Fメインのエリア\n",[235,23285,23286,23288,23290,23292,23294,23296,23299,23301],{"class":237,"line":298},[235,23287,1506],{"class":499},[235,23289,1225],{"class":495},[235,23291,8017],{"class":1375},[235,23293,1382],{"class":499},[235,23295,1517],{"class":499},[235,23297,23298],{"class":245},"l-center-area",[235,23300,1517],{"class":499},[235,23302,1487],{"class":499},[235,23304,23305],{"class":237,"line":380},[235,23306,263],{"emptyLinePlaceholder":262},[235,23308,23309],{"class":237,"line":465},[235,23310,23311],{"class":519},"            \u002F\u002Fサムネイル\n",[235,23313,23314,23316,23318,23320,23322,23324,23326,23328,23330,23332,23334,23337,23339,23341,23343,23345,23347,23349,23351,23353,23355,23358,23360],{"class":237,"line":590},[235,23315,9208],{"class":499},[235,23317,5066],{"class":495},[235,23319,21066],{"class":1375},[235,23321,1382],{"class":499},[235,23323,1517],{"class":499},[235,23325,18745],{"class":245},[235,23327,1517],{"class":499},[235,23329,8005],{"class":1375},[235,23331,1382],{"class":499},[235,23333,1517],{"class":499},[235,23335,23336],{"class":245},"c-article-thumbnail",[235,23338,1517],{"class":499},[235,23340,22813],{"class":1375},[235,23342,1382],{"class":499},[235,23344,1517],{"class":499},[235,23346,18745],{"class":245},[235,23348,1517],{"class":499},[235,23350,22825],{"class":1375},[235,23352,1382],{"class":499},[235,23354,1517],{"class":499},[235,23356,23357],{"class":245},"content.title",[235,23359,1517],{"class":499},[235,23361,1487],{"class":499},[235,23363,23364],{"class":237,"line":604},[235,23365,263],{"emptyLinePlaceholder":262},[235,23367,23368],{"class":237,"line":612},[235,23369,23370],{"class":519},"            \u002F\u002Fタグとカテゴリーのバッチ\n",[235,23372,23373,23375,23377,23379,23381,23383,23386,23388],{"class":237,"line":623},[235,23374,9208],{"class":499},[235,23376,1225],{"class":495},[235,23378,8005],{"class":1375},[235,23380,1382],{"class":499},[235,23382,1517],{"class":499},[235,23384,23385],{"class":245},"p-article-badge p-badge-container",[235,23387,1517],{"class":499},[235,23389,1487],{"class":499},[235,23391,23392,23394,23396,23398,23400,23402,23405,23407,23409,23411,23413,23416,23418,23420,23422,23424,23427,23429,23431,23433,23435,23438,23440],{"class":237,"line":634},[235,23393,20959],{"class":499},[235,23395,20320],{"class":495},[235,23397,8005],{"class":1375},[235,23399,1382],{"class":499},[235,23401,1517],{"class":499},[235,23403,23404],{"class":245},"c-tag-badge u-blue",[235,23406,1517],{"class":499},[235,23408,20516],{"class":1375},[235,23410,1382],{"class":499},[235,23412,1517],{"class":499},[235,23414,23415],{"class":245},"(c,index) in content.category",[235,23417,1517],{"class":499},[235,23419,20528],{"class":1375},[235,23421,1382],{"class":499},[235,23423,1517],{"class":499},[235,23425,23426],{"class":245},"'category-'+index",[235,23428,1517],{"class":499},[235,23430,20547],{"class":1375},[235,23432,1382],{"class":499},[235,23434,1517],{"class":499},[235,23436,23437],{"class":245},"'\u002Fcategory\u002F'+c",[235,23439,1517],{"class":499},[235,23441,1487],{"class":499},[235,23443,23444,23447,23449,23451,23454,23456,23458],{"class":237,"line":641},[235,23445,23446],{"class":499},"                    \u003C",[235,23448,235],{"class":495},[235,23450,1524],{"class":499},[235,23452,23453],{"class":519},"{{$store.getters['getCategoryTextBySlug'](c)}}",[235,23455,1530],{"class":499},[235,23457,235],{"class":495},[235,23459,1487],{"class":499},[235,23461,23462,23464,23466],{"class":237,"line":653},[235,23463,21110],{"class":499},[235,23465,20320],{"class":495},[235,23467,1487],{"class":499},[235,23469,23470,23472,23474,23476,23478,23480,23483,23485,23487,23489,23491,23494,23496,23498,23500,23502,23505,23507,23509,23511,23513,23516,23518],{"class":237,"line":661},[235,23471,20959],{"class":499},[235,23473,20320],{"class":495},[235,23475,8005],{"class":1375},[235,23477,1382],{"class":499},[235,23479,1517],{"class":499},[235,23481,23482],{"class":245},"c-tag-badge",[235,23484,1517],{"class":499},[235,23486,20516],{"class":1375},[235,23488,1382],{"class":499},[235,23490,1517],{"class":499},[235,23492,23493],{"class":245},"(t,index) in content.tag",[235,23495,1517],{"class":499},[235,23497,20528],{"class":1375},[235,23499,1382],{"class":499},[235,23501,1517],{"class":499},[235,23503,23504],{"class":245},"'tag-'+index",[235,23506,1517],{"class":499},[235,23508,20547],{"class":1375},[235,23510,1382],{"class":499},[235,23512,1517],{"class":499},[235,23514,23515],{"class":245},"'\u002Ftag\u002F'+t",[235,23517,1517],{"class":499},[235,23519,1487],{"class":499},[235,23521,23522,23524,23526,23528,23531,23533,23535],{"class":237,"line":670},[235,23523,23446],{"class":499},[235,23525,235],{"class":495},[235,23527,1524],{"class":499},[235,23529,23530],{"class":519},"{{$store.getters['getTagTextBySlug'](t)}}",[235,23532,1530],{"class":499},[235,23534,235],{"class":495},[235,23536,1487],{"class":499},[235,23538,23539,23541,23543],{"class":237,"line":678},[235,23540,21110],{"class":499},[235,23542,20320],{"class":495},[235,23544,1487],{"class":499},[235,23546,23547,23549,23551],{"class":237,"line":686},[235,23548,9241],{"class":499},[235,23550,1225],{"class":495},[235,23552,1487],{"class":499},[235,23554,23555],{"class":237,"line":694},[235,23556,263],{"emptyLinePlaceholder":262},[235,23558,23559,23561,23563,23565,23567,23569,23572,23574,23576,23579,23581,23583],{"class":237,"line":702},[235,23560,9208],{"class":499},[235,23562,20488],{"class":495},[235,23564,8005],{"class":1375},[235,23566,1382],{"class":499},[235,23568,1517],{"class":499},[235,23570,23571],{"class":245},"c-article-header",[235,23573,1517],{"class":499},[235,23575,1524],{"class":499},[235,23577,23578],{"class":519},"{{ content.title }}",[235,23580,1530],{"class":499},[235,23582,20488],{"class":495},[235,23584,1487],{"class":499},[235,23586,23587],{"class":237,"line":712},[235,23588,263],{"emptyLinePlaceholder":262},[235,23590,23591],{"class":237,"line":723},[235,23592,23593],{"class":519},"            \u002F\u002F 更新一時など\n",[235,23595,23596,23598,23600,23602,23604,23606,23609,23611],{"class":237,"line":730},[235,23597,9208],{"class":499},[235,23599,1225],{"class":495},[235,23601,8005],{"class":1375},[235,23603,1382],{"class":499},[235,23605,1517],{"class":499},[235,23607,23608],{"class":245},"p-articler-date",[235,23610,1517],{"class":499},[235,23612,1487],{"class":499},[235,23614,23615,23617,23619,23621,23623,23625,23628,23630,23633,23636,23639,23641,23643,23646,23648,23651,23654,23656,23658],{"class":237,"line":741},[235,23616,20959],{"class":499},[235,23618,235],{"class":495},[235,23620,8005],{"class":1375},[235,23622,1382],{"class":499},[235,23624,1517],{"class":499},[235,23626,23627],{"class":245},"c-date",[235,23629,1517],{"class":499},[235,23631,23632],{"class":499},">\u003C",[235,23634,23635],{"class":495},"fa-icon",[235,23637,23638],{"class":1375}," :icon",[235,23640,1382],{"class":499},[235,23642,1517],{"class":499},[235,23644,23645],{"class":245},"['fa', 'history']",[235,23647,1517],{"class":499},[235,23649,23650],{"class":499},"\u002F>",[235,23652,23653],{"class":519},"{{ updateAt }}",[235,23655,1530],{"class":499},[235,23657,235],{"class":495},[235,23659,1487],{"class":499},[235,23661,23662,23664,23666,23668,23670,23672,23674,23676,23678,23680,23682,23684,23686,23689,23691,23693,23696,23698,23700],{"class":237,"line":752},[235,23663,20959],{"class":499},[235,23665,235],{"class":495},[235,23667,8005],{"class":1375},[235,23669,1382],{"class":499},[235,23671,1517],{"class":499},[235,23673,23627],{"class":245},[235,23675,1517],{"class":499},[235,23677,23632],{"class":499},[235,23679,23635],{"class":495},[235,23681,23638],{"class":1375},[235,23683,1382],{"class":499},[235,23685,1517],{"class":499},[235,23687,23688],{"class":245},"['far', 'clock']",[235,23690,1517],{"class":499},[235,23692,23650],{"class":499},[235,23694,23695],{"class":519},"{{ createdAt }}",[235,23697,1530],{"class":499},[235,23699,235],{"class":495},[235,23701,1487],{"class":499},[235,23703,23704,23706,23708],{"class":237,"line":763},[235,23705,9241],{"class":499},[235,23707,1225],{"class":495},[235,23709,1487],{"class":499},[235,23711,23712],{"class":237,"line":774},[235,23713,263],{"emptyLinePlaceholder":262},[235,23715,23716],{"class":237,"line":785},[235,23717,23718],{"class":519},"            \u002F\u002F マークダウンのレンダリング箇所\n",[235,23720,23721,23723,23725,23727,23729,23731,23733,23735],{"class":237,"line":794},[235,23722,9208],{"class":499},[235,23724,22551],{"class":495},[235,23726,22554],{"class":1375},[235,23728,1382],{"class":499},[235,23730,1517],{"class":499},[235,23732,12519],{"class":245},[235,23734,1517],{"class":499},[235,23736,22565],{"class":499},[235,23738,23739,23741,23743],{"class":237,"line":806},[235,23740,9278],{"class":499},[235,23742,1225],{"class":495},[235,23744,1487],{"class":499},[235,23746,23747],{"class":237,"line":815},[235,23748,263],{"emptyLinePlaceholder":262},[235,23750,23751],{"class":237,"line":823},[235,23752,23753],{"class":519},"        \u002F\u002Fサイドメニュー\n",[235,23755,23756,23758,23761],{"class":237,"line":833},[235,23757,1506],{"class":499},[235,23759,23760],{"class":495},"sidemenu",[235,23762,5081],{"class":499},[235,23764,23765,23767,23769],{"class":237,"line":3537},[235,23766,1539],{"class":499},[235,23768,1225],{"class":495},[235,23770,1487],{"class":499},[235,23772,23773,23775,23777],{"class":237,"line":3542},[235,23774,22570],{"class":499},[235,23776,1225],{"class":495},[235,23778,1487],{"class":499},[235,23780,23781,23783,23785],{"class":237,"line":3547},[235,23782,1530],{"class":499},[235,23784,1484],{"class":495},[235,23786,1487],{"class":499},[74,23788,23789],{"id":23789},"静的書き出しをしてみる",[13,23791,23792,23793,23798,23799,6554,23801,23804],{},"それではpagesファイル、マークダウンも作成したのでとりあえずある分だけ静的書き出ししてみましょう。",[197,23794,23797],{"href":23795,"rel":23796},"https:\u002F\u002Fcontent.nuxtjs.org\u002Fja\u002Fadvanced#%E9%9D%99%E7%9A%84%E3%82%B5%E3%82%A4%E3%83%88%E7%94%9F%E6%88%90",[201],"公式の説明","がありますが",[39,23800,23108],{},[39,23802,23803],{},"generate","オプションを設定必要があります。では以下のように設定します。",[226,23806,23808],{"className":3990,"code":23807,"filename":23108,"language":3992,"meta":231,"style":231},"generate: {\n    async routes () {\n      const { $content } = require('@nuxt\u002Fcontent')\n      const files = await $content({ deep: true }).only(['path']).fetch()\n      return files.map(file => file.path === '\u002Findex' ? '\u002F' : file.path);\n    }\n},\n",[39,23809,23810,23818,23829,23855,23904,23961,23965],{"__ignoreMap":231},[235,23811,23812,23814,23816],{"class":237,"line":238},[235,23813,23803],{"class":241},[235,23815,500],{"class":499},[235,23817,1276],{"class":499},[235,23819,23820,23822,23824,23827],{"class":237,"line":249},[235,23821,19931],{"class":519},[235,23823,1457],{"class":252},[235,23825,23826],{"class":495}," () ",[235,23828,1976],{"class":499},[235,23830,23831,23834,23836,23838,23840,23842,23844,23846,23848,23851,23853],{"class":237,"line":259},[235,23832,23833],{"class":1375},"      const",[235,23835,6813],{"class":499},[235,23837,19971],{"class":519},[235,23839,14121],{"class":499},[235,23841,4116],{"class":499},[235,23843,1702],{"class":252},[235,23845,1705],{"class":495},[235,23847,1345],{"class":499},[235,23849,23850],{"class":245},"@nuxt\u002Fcontent",[235,23852,1345],{"class":499},[235,23854,1953],{"class":495},[235,23856,23857,23859,23862,23864,23866,23868,23870,23872,23874,23876,23878,23880,23882,23884,23886,23888,23890,23892,23894,23897,23899,23901],{"class":237,"line":266},[235,23858,23833],{"class":1375},[235,23860,23861],{"class":519}," files",[235,23863,4116],{"class":499},[235,23865,19968],{"class":1269},[235,23867,19971],{"class":252},[235,23869,1705],{"class":495},[235,23871,1930],{"class":499},[235,23873,19978],{"class":495},[235,23875,500],{"class":499},[235,23877,5805],{"class":4702},[235,23879,14121],{"class":499},[235,23881,1715],{"class":495},[235,23883,1694],{"class":499},[235,23885,19991],{"class":252},[235,23887,20081],{"class":495},[235,23889,1345],{"class":499},[235,23891,2098],{"class":245},[235,23893,1345],{"class":499},[235,23895,23896],{"class":495},"])",[235,23898,1694],{"class":499},[235,23900,20036],{"class":252},[235,23902,23903],{"class":495},"()\n",[235,23905,23906,23909,23911,23913,23916,23918,23921,23923,23926,23928,23930,23932,23934,23937,23939,23942,23944,23946,23948,23951,23953,23955,23957,23959],{"class":237,"line":275},[235,23907,23908],{"class":1269},"      return",[235,23910,23861],{"class":519},[235,23912,1694],{"class":499},[235,23914,23915],{"class":252},"map",[235,23917,1705],{"class":495},[235,23919,23920],{"class":4527},"file",[235,23922,4533],{"class":1375},[235,23924,23925],{"class":519}," file",[235,23927,1694],{"class":499},[235,23929,2098],{"class":519},[235,23931,19633],{"class":499},[235,23933,503],{"class":499},[235,23935,23936],{"class":245},"\u002Findex",[235,23938,1345],{"class":499},[235,23940,23941],{"class":499}," ?",[235,23943,503],{"class":499},[235,23945,4055],{"class":245},[235,23947,1345],{"class":499},[235,23949,23950],{"class":499}," :",[235,23952,23925],{"class":519},[235,23954,1694],{"class":499},[235,23956,2098],{"class":519},[235,23958,1715],{"class":495},[235,23960,1348],{"class":499},[235,23962,23963],{"class":237,"line":283},[235,23964,2181],{"class":499},[235,23966,23967],{"class":237,"line":291},[235,23968,1414],{"class":499},[13,23970,23971,23972,23975,23976,23978,23979,23981,23982,23984],{},"これは何をやっているかというと、",[39,23973,23974],{},"$content({ deep: true })","を使用してcontent配下にあるマークダウン一式とそのパスを全て取得して、Nuxtに生成すべきルートを伝えています。なぜこれを行う必要があるのかという理由ですが、Nuxt.jsは",[39,23977,19889],{},"配下の構成を元にして必要なページを生成します。しかしどんなルート名になるかわからない",[39,23980,22519],{},"というファイル（動的ルート）がある場合は、とりうるルートを",[39,23983,23803],{},"オプション内で明示的に指定する必要があります。",[13,23986,23987],{},"Nuxt.js自身はcontents配下の構成とパスがどうなっているのかわからないので、Nuxt Contentから取得します。",[13,23989,23990,23992],{},[39,23991,23108],{},"でSSGができる設定にしたら",[226,23994,23997],{"className":23995,"code":23996,"language":934},[932],"npm run generate\n",[39,23998,23996],{"__ignoreMap":231},[13,24000,24001,24002,24005],{},"を叩くことで静的書き出しが行われます。書き出し後には",[39,24003,24004],{},"dist\u002F","というビルドファイルが作成されます。",[226,24007,24010],{"className":24008,"code":24009,"language":934},[932],"npm run start\n",[39,24011,24009],{"__ignoreMap":231},[13,24013,24014,24015,24017],{},"でひとまずローカル環境で",[39,24016,24004],{},"をドキュメントルートとしてみることができます。以下のような構成で作っていた場合、",[226,24019,24022],{"className":24020,"code":24021,"language":934},[932],"├── content\n│   ├── articles\n│   │   ├── sample.md\n│\n├── pages\n│   ├── articles\n│   　   ├── _slug.vue\n",[39,24023,24021],{"__ignoreMap":231},[13,24025,24026,24029,24030,24032],{},[39,24027,24028],{},"http:\u002F\u002Flocalhost:3000\u002Farticles\u002Fsample","にアクセスすると内容が見れると思います。curlで",[39,24031,24028],{},"でアクセスしてきちんと静的HTMLが書き出されているかを確認してみましょう。",[74,24034,24035],{"id":24035},"以上で基本的な構成の作成が完了",[13,24037,24038,24039,24042,24043,24045,24046,24048],{},"スタイルとかの問題はあるかもしれませんが、ひとまず",[39,24040,24041],{},"pages","・",[39,24044,12519],{},"ディレクトリ、",[39,24047,23108],{},"の設定を行えばブログ的な構成とCMSとしての機能が実装できました。次回は記事の一覧ページとページング処理について解説していきます。",[2399,24050,24051],{},"html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .sbqyR, html code.shiki .sbqyR{--shiki-default:#FF9CAC}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}",{"title":231,"searchDepth":259,"depth":259,"links":24053},[24054,24059,24066,24067],{"id":22425,"depth":249,"text":22425,"children":24055},[24056,24057,24058],{"id":22428,"depth":259,"text":22428},{"id":22477,"depth":259,"text":22478},{"id":22513,"depth":259,"text":22514},{"id":22691,"depth":249,"text":22691,"children":24060},[24061,24062,24063,24064,24065],{"id":22702,"depth":259,"text":22702},{"id":23063,"depth":259,"text":23064},{"id":23094,"depth":259,"text":23094},{"id":23172,"depth":259,"text":23172},{"id":23195,"depth":259,"text":23195},{"id":23789,"depth":249,"text":23789},{"id":24035,"depth":249,"text":24035},[2427],"2021-05-05","Nuxt Content × SSG で作る静的ブログ。目次、記事内画像、どんな項目を記事にレンダーできるかと静的書き出しについて説明。",{},"\u002Fseries\u002Fnuxt-content-blog-2",{"title":22401,"description":24070},"series\u002Fnuxt-content-blog-2",[1262,18699],"G0AV4H-Vu8cOAUAeRcjFkqt5-eZKAcs9pHDQjdPhG4E",1780987140587]