è¯ãäžæ¥ãåéïŒ
WebpackãParcelãªã©ã®ã¢ãžã¥ãŒã«ãã«ããŒãŸãã¯ãã³ãã©ãŒã®äž»ãªç®çã¯ãã¢ããªã±ãŒã·ã§ã³ã®å®è¡ã«å¿ èŠãªãã¹ãŠã®ã¢ãžã¥ãŒã«ããã€ã³ããã¯ã¹ã«å«ãŸãã1ã€ã®çž®å°ïŒæ¬çªãã«ãçšïŒã¹ã¯ãªããã«æ£ããé åºã§å«ãŸããããã«ããããšã§ãã htmlã
å®éããã«ããŒã¯ãååãšããŠãJSã ãã§ãªããHTMLãCSSãã¡ã€ã«ãæé©åã§ããLessãSassãCSSã«ãTypeScriptãReact and VueïŒJSXïŒãJavaScriptã«å€æããç»åããªãŒãã£ãªããããªãªã©ãæäœã§ããŸããããŒã¿åœ¢åŒãããã³æ¬¡ã®ãããªè¿œå æ©èœãæäŸããŸã:(äœ¿çšæžã¿ïŒãªãœãŒã¹ãŸãã¯ãœãŒã¹ã®ãããïŒãœãŒã¹ãããïŒã®äœæããã³ãã«å šäœãšãã®åã ã®éšåïŒã¢ãžã¥ãŒã«ãã©ã€ãã©ãªïŒã®ãµã€ãºã®èŠèŠç衚çŸãã³ãŒããéšåïŒãã£ã³ã¯ïŒã«åå²ããïŒä»¥äžãå«ãïŒæ°ãåå©çšç®çïŒããšãã°ãè€æ°ã®ã¢ãžã¥ãŒã«ã§äœ¿çšãããã©ã€ãã©ãªãå¥ã ã®ãã¡ã€ã«ã«åãåºãããŠ1åã ãããŒããããïŒãnpmããã®ããã±ãŒãžã®ã¹ããŒãããŒãïŒããšãã°ãmoment.jsãããã·ã¢ã®ããŒã«ãªãŒãŒã·ã§ã³ã®ã¿ãããŒãããïŒãç¹å®ã®ã¿ã¹ã¯ã解決ããããã®ããããçš®é¡ã®ãã©ã°ã€ã³ç
ãã®ç¹ã§ãWebpackãééããªããªãŒãããŠããŸãããããããã®åªããããŒã«ã«ãã£ãŠæäŸãããæ©èœã®ã»ãšãã©ãå¿ èŠãšãããªããããžã§ã¯ããéçºããŠããå Žåã¯ã©ããªãã§ãããããç¿åŸãšäœ¿çšãç°¡åãªãã®ãã¯ãããžãŒã®ä»£æ¿ææ®µã¯ãããŸããïŒç§ã«ãšã£ãŠããã®è³ªåã«å¯Ÿããçãã¯ããŒã»ã«ã§ãããã¡ãªã¿ã«ãWebpackã«ã€ããŠç¥ãããæ¹ã¯ããã¡ãã®åç»ãã芧ã«ãªãããšããå§ãããŸãããã®ãã¥ãŒããªã¢ã«ã®Webpackèšå®ãå«ãç§ã®ãã¡ã€ã«ã¯ããã«ãããŸãã
ããªãã®èš±å¯ãåŸãŠãç¹ã«ãã·ã¢èªã§å©çšã§ããã®ã§ãç§ã¯èªåã®èšèã§ããã¥ã¡ã³ããå話ããŸããããå®çšçãªã³ã³ããŒãã³ãã«çŠç¹ãåœãŠãŸãïŒãã³ãã¬ãŒãæååãšåçã€ã³ããŒãã䜿çšããŠãJavaScriptã§3ããŒãžã§æ§æãããSPAãäœæããŸãã CSSã§ã¢ããªã±ãŒã·ã§ã³ã®ã¹ã¿ã€ã«ãèšå®ããTypeScriptã§ç°¡åãªé¢æ°ãèšè¿°ãããããã¢ããªã±ãŒã·ã§ã³ã«ã€ã³ããŒãããSassã䜿çšããŠãã®é¢æ°ã®çµæã®ã³ã³ãããŒã®ã¹ã¿ã€ã«ãèšå®ããéçºã¢ãŒããšæ¬çªã¢ãŒãã®äž¡æ¹ã§Parcelã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããŸãã
ãããžã§ã¯ãã³ãŒãã¯ãã¡ãã§ãã
èå³ã®ããæ¹ã¯ãã©ããŒããŠãã ããã
å¿çš
æºåã¯ããã§ããïŒããã§ã¯è¡ããŸãããã
parcel-tutorialãã£ã¬ã¯ããªãäœæããŸãã
ããã«å ¥ããã䜿çšããŠãããžã§ã¯ããåæåã
npm init -yãŸãã
index.htmlãã¡ã€ã«ãäœæããŸããæšæºã®ããŒãã¹ãã©ããã«ããŒãã³ãã¬ãŒãã®1ã€ã䜿çšããŸãã
<head>
...
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<!-- Bootstrap class -->
<body class="text-center">
<! -- Main script -->
<script src="index.js"></script>
</body>
Bootstrap ã®å ¬åŒWebãµã€ãã«ã¢ã¯ã»ã¹ãã[äŸ]ã»ã¯ã·ã§ã³ã«ç§»åããŠãã«ã¹ã¿ã ã³ã³ããŒãã³ãã®ã«ããŒãèŠã€ããCtrl + UïŒCmd + UïŒãæŒããŠããŒãžã³ãŒãã衚瀺ããŸãã
srcãã£ã¬ã¯ããªãäœæãããšããã®äžã«jsãšcssã®2ã€ã®ãã©ã«ãããããŸãã
jsãã£ã¬ã¯ããªã«æ¬¡ã®ãã¡ã€ã«ãäœæããŸãïŒheader.jsãfooter.jsãhome.jsãprojects.jsãcontact.jsããããã¯ã¢ãžã¥ãŒã«ããŸãã¯å¿ èŠã«å¿ããŠãã¢ããªã±ãŒã·ã§ã³ã®ã³ã³ããŒãã³ãã§ããããããŒãããã¿ãŒãã¡ã€ã³ããŒãžããã³ãã®ä»ã®ããŒãžã®ã³ã³ãã³ãã§ãã
cssãã£ã¬ã¯ããªã«ãstyle.cssãã¡ã€ã«ãäœæããŸãã
çŸæç¹ã§ã¯ããããžã§ã¯ãã®æ§é ã¯æ¬¡ã®ããã«ãªã£ãŠããŸãã
-- parcel-tutorial
-- src
-- css
-- style.css
-- js
-- contact.js
-- footer.js
-- header.js
-- home.js
-- projects.js
-- index.html
-- index.js
-- package.json
ããŒãã¹ãã©ããã«æ»ãã
å°ããªå€æŽãå ããŠãããŒãžã³ãŒãã察å¿ããã¢ãžã¥ãŒã«ã«ã³ããŒããŠè²Œãä»ããŸãã
header.jsïŒ
export default `
<header class="masthead mb-auto">
<div class="inner">
<h3 class="masthead-brand">Parcel Tutorial</h3>
<nav class="nav nav-masthead justify-content-center">
<a class="nav-link active" name="home">Home</a>
<a class="nav-link" name="projects">Projects</a>
<a class="nav-link" name="contact">Contact</a>
</nav>
</div>
</header>
`.trim()
ãªã³ã¯ã®hrefãnameã«å€æŽããããšã«æ³šæããŠãã ããã
footer.jsïŒ
export default `
<footer class="mastfoot mt-auto">
<div class="inner">
<p>© 2020. All rights reserved.</p>
</div>
</footer>
`.trim()
home.jsïŒ
export default `
<h1 class="cover-heading">Home page</h1>
<p class="lead">Home page content</p>
`.trim()
projects.jsïŒ
export default `
<h1 class="cover-heading">Projects page</h1>
<p class="lead">Projects page content</p>
`.trim()
contact.jsïŒ
export default `
<h1 class="cover-heading">Contact page</h1>
<p class="lead">Contact page content</p>
`.trim()
style.cssããstyle.cssã«ã¹ã¿ã€ã«ãã³ããŒããããšãå¿ããªãã§ãã ããã
index.jsãéããŸãã
ããããŒãããã¿ãŒãã¹ã¿ã€ã«ãã€ã³ããŒãããŸãããã
import header from './src/js/header.js'
import footer from './src/js/footer.js'
import './src/css/style.css'
ãªã³ã¯ãã¯ãªãã¯ãããšãã¡ã€ã³ããŒãžãšä»ã®ããŒãžã®ã³ã³ãã³ããåçã«èªã¿èŸŒãŸãããããæ¬¡ã®ãããªãªããžã§ã¯ããäœæããŸãã
const pages = {
home: import('./src/js/home.js'),
projects: import('./src/js/projects.js'),
contact: import('./src/js/contact.js')
}
ãã®ãªããžã§ã¯ãã®ããããã£ã®ååã¯ã察å¿ããïŒãŠãŒã¶ãŒãèŠæ±ããïŒããŒãžã§ãã
以åã«ã€ã³ããŒãããããããŒããã³ããã¿ãŒã³ã³ããŒãã³ãã䜿çšããŠãã¹ã¿ãŒãããŒãžãçæããŸãã
// Bootstrap classes
document.body.innerHTML = `
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
${header}
<main role="main" class="inner cover"></main>
${footer}
</div>
`.trim()
ããŒãžã®ã³ã³ãã³ãã¯ã¡ã€ã³èŠçŽ ã«è¡šç€ºããããããæ¬¡ã®ããã«å®çŸ©ããŸãã
const mainEl = document.querySelector('main')
ããŒãžã¬ã³ããªã³ã°é¢æ°ãäœæããŸãã
const renderPage = async name => {
const template = await pages[name]
mainEl.innerHTML = template.default
}
察å¿ããã¢ãžã¥ãŒã«ãããŒããããã®ãåŸ ã€å¿ èŠããããããasync / awaitã䜿çšããŸãïŒawaitããŒã¯ãŒãã¯é¢æ°ã®å®è¡ãäžæåæ¢ããŸãïŒããã®é¢æ°ã¯ãèŠæ±ãããããŒãžã®ååïŒnameïŒãåãåããããã䜿çšããŠãpagesãªããžã§ã¯ãïŒpages [name]ïŒã®å¯Ÿå¿ããããããã£ã«ã¢ã¯ã»ã¹ããŸããæ¬¡ã«ãçµæã®ãã³ãã¬ãŒããmainElã«æ¿å ¥ããŸããå®éãawaitã¯ããã³ãã¬ãŒããå«ãModuleãªããžã§ã¯ããè¿ããŸãããããã£ãŠãmainElã«ããŒã¯ã¢ãããšããŠãã³ãã¬ãŒããæ¿å ¥ãããšãã¯ãModuleãªããžã§ã¯ãã®ããã©ã«ãããããã£ãåç §ããå¿ èŠããããŸãïŒã¢ãžã¥ãŒã«ã¯ããã©ã«ãã§ãšã¯ã¹ããŒããããŸãïŒãããããªããšããšã©ãŒãçºçããŸãããªããžã§ã¯ããHTMLã«å€æã§ããŸããã
ã¡ã€ã³ããŒãžãã¬ã³ããªã³ã°ããŸãã
renderPage('home')
çŸåšã®ããŒãžã«å¯Ÿå¿ããã¢ã¯ãã£ããªã³ã¯ã«ã¯ãã¢ã¯ãã£ãã¯ã©ã¹ããããŸããæ°ããããŒãžãã¬ã³ããªã³ã°ãããšãã«ã¯ã©ã¹ãåãæ¿ããå¿ èŠããããŸãããã«ããŒé¢æ°ãå®è£ ããŸãããïŒ
const toggleClass = (activeLink, currentLink) => {
if (activeLink === currentLink) {
return;
} else {
activeLink.classList.remove('active')
currentLink.classList.add('active')
}
}
ãã®é¢æ°ã¯ãã¯ã©ã¹ãã¢ã¯ãã£ããªãªã³ã¯ïŒactiveLinkïŒãšã¯ãªãã¯ããããªã³ã¯ïŒcurrentLinkïŒã®2ã€ã®åŒæ°ãåããŸããæå®ããããªã³ã¯ãäžèŽããå ŽåãäœãããŸããããã以å€ã®å Žåã¯ãã¯ã©ã¹ã倿ŽããŸãã
æåŸã«ããªã³ã¯ã¯ãªãã¯ãã³ãã©ãŒã远å ããå¿ èŠããããŸãããã1ã€ã®ãã«ããŒé¢æ°ãå®è£ ããŸãããïŒ
const initClickHandlers = () => {
const navEl = document.querySelector('nav')
navEl.addEventListener('click', ev => {
if (ev.target.tagName === 'A') {
const activeLink = navEl.querySelector('.active')
const currentLink = ev.target
toggleClass(activeLink, currentLink)
renderPage(currentLink.name)
}
})
}
ãã®é¢æ°ã§ã¯ãæåã«navèŠçŽ ãèŠã€ããŸããæ¬¡ã«ãå§ä»»ãéããŠããªã³ã¯ã®ã¯ãªãã¯ãåŠçããŸããã¿ãŒã²ããèŠçŽ ãAã¿ã°ã®å Žåãã¢ã¯ãã£ããªã³ã¯ïŒã¢ã¯ãã£ãã¯ã©ã¹ãšã®ãªã³ã¯ïŒãçŸåšã®ãªã³ã¯ïŒã¯ãªãã¯ããããªã³ã¯ïŒãååŸããã¯ã©ã¹ã倿ŽããŠããŒãžãã¬ã³ããªã³ã°ããŸããçŸåšã®ãªã³ã¯ã®name屿§ã®å€ã¯ãrenderPageåŒæ°ãšããŠæž¡ãããŸãã
ã¢ããªã¯ã»ãŒå®æã§ãããã ããParcelã䜿çšããŠãããžã§ã¯ããæ§ç¯ããåã«ã次ã®ç¹ã«æ³šæããå¿ èŠããããŸããçŸåšãããŒã¿ã䜿çšã§ããŸããã«ããåçã¢ãžã¥ãŒã«ã®ãµããŒãã¯90ïŒ ã§ããããã¯ãããããããŸããããŠãŒã¶ãŒã®10ïŒ ãå€±ãæºåã¯ã§ããŠããŸããããããã£ãŠãã³ãŒããææ°ã§ã¯ãªãæ§æã«å€æããå¿ èŠããããŸããããã«ã¯è»¢çã«äœ¿çšãããŸãã 2ã€ã®è¿œå ã¢ãžã¥ãŒã«ãæ¥ç¶ããå¿ èŠããããŸãã
import "core-js/stable";
import "regenerator-runtime/runtime";
ãããã®ããã±ãŒãžã¯npmã§ã¯ã€ã³ã¹ããŒã«ãããªãããšã«æ³šæããŠãã ããã
ãŸãã2ã€ã®æ°å€ãå ç®ãã颿°ã®ãããªéåžžã«åçŽãªé¢æ°ãTypeScriptã«ããã«å®è£ ããŸãããã
次ã®å 容ã§jsãã£ã¬ã¯ããªã«index.tsãã¡ã€ã«ãäœæããŸãã
export const sum = (a: number, b: number): number => a + b
JavaScriptãšã®å¯äžã®éãã¯ããã¡ã€ã«æ¡åŒµåïŒ.tsïŒãé€ããŠã颿°ã«ãã£ãŠåãå ¥ããããŠè¿ãããå€ã®ã¿ã€ãïŒãã®å Žåã¯numberïŒãæç€ºçã«æå®ããããšã§ããå®éãæ»ãåã®å®çŸ©ã«éå®ããããšãã§ããŸããTypeScriptã¯ãæ»ãå€ãæ°å€ã®å Žåãæž¡ãããåŒæ°ã¯æ°å€ã§ãªããã°ãªããªãããšãç¥ã£ãŠããã»ã©è³¢ãã§ããæ°ã«ããªãã§ã
ãã®é¢æ°ãindex.jsã«ã€ã³ããŒãããŸãããïŒ
import { sum } from './src/js/index.ts'
ãããŠãrenderPageã®åŒæ°1ãš2ã䜿çšããŠåŒã³åºããŸãã
const renderPage = async name => {
// ...
mainEl.insertAdjacentHTML('beforeend', `
<output>Result of 1 + 2 -> <span>${sum(1, 2)}<span></output>
`)
}
Sassã䜿çšãã颿°çµæã³ã³ããã®ã¹ã¿ã€ãªã³ã°ãcssãã©ã«ããŒã«ã次ã®å 容ã®style.scssãã¡ã€ã«ãäœæããŸãã
$color: #8e8e8e;
output {
color: $color;
border: 1px solid $color;
border-radius: 4px;
padding: .5rem;
user-select: none;
transition: transform .2s;
& span {
color: #eee;
}
&:hover {
transform: scale(1.1);
}
}
ãããã®ã¹ã¿ã€ã«ãindex.jsã«ã€ã³ããŒãããŸãããïŒ
import './src/css/style.scss'
TypeScriptãšSassãnpmã§ã€ã³ã¹ããŒã«ããŠããªãããšã«å床泚æããŠãã ããã
ã¢ããªã±ãŒã·ã§ã³ã宿ããŸãããããŒã»ã«ã«ç§»ããŸãã
å°å
Parcelãã°ããŒãã«ã«ã€ã³ã¹ããŒã«ããã«
npm i parcel-bundler -gã¯ãã¿ãŒããã«ã§ã³ãã³ããå®è¡ããå¿
èŠããããŸãã
package.jsonãéããéçºã¢ãŒããšæ¬çªã¢ãŒãã§å®è¡ããããã«Parcelãæ§æããŸãã
"scripts": {
"dev": "parcel index.html --no-source-maps --open",
"pro": "parcel build index.html --no-source-maps --no-cache"
},
ããŒã
npm run devã¯éçºçšã®ãããžã§ã¯ãã®æ§ç¯ãéå§npm run proããããŒã ã¯çç£çšã«éå§ããŸããããããããããã¹ãŠã®ãã©ã°ã¯ã©ãããæå³ã§ããïŒãããŠããªãnpmçµç±ã§BabelãTypeScriptãSassãã€ã³ã¹ããŒã«ããªãã£ãã®ã§ããïŒ
äºå®ãParcelã¯ãã¢ããªã±ãŒã·ã§ã³ã§ã®ã€ã³ããŒããŸãã¯äœ¿çšãæ€åºãããšããã¹ãŠã®äŸåé¢ä¿ãèªåçã«ã€ã³ã¹ããŒã«ããŸããããšãã°ãParcelã.scssãã¡ã€ã«ããã€ã³ããŒããããã¹ã¿ã€ã«ã·ãŒããæ€åºãããšãSassãã€ã³ã¹ããŒã«ãããŸãã
次ã«ãããŒã ãšãã©ã°ã«ã€ããŠèª¬æããŸãã
ãããžã§ã¯ããéçºã¢ãŒãã§ãã«ãããã«ã¯ãã³ãã³ãã䜿çšããŸã
parcel index.htmlãããã§ãindex.htmlã¯ã¢ããªã±ãŒã·ã§ã³ã®ãšã³ããªãã€ã³ãã§ããã¡ã€ã³ã¹ã¯ãªãããžã®ãªã³ã¯ãå«ããã¡ã€ã«ããŸãããã®ã³ãã³ãã¯localhostïŒ1234ã§ããŒã«ã«ãµãŒããŒãèµ·åããŸãã
ãã®ãã©ã°
--no-source-mapsã¯ããªãœãŒã¹ããããäžèŠã§ããããšãæå³ããŸãã
åœæ
--openããŒã«ã«ãµãŒããŒã®ãã©ãŠã¶ã«ãã«ãããåŸãindex.htmlãéãããã«Parcelã«æç€ºããŸãã
å®çšŒåã¢ãŒãã§ãããžã§ã¯ãããã«ãããã«ã¯ãã³ãã³ãã䜿çšã
parcel build index.htmlãŸãããã®ãããªã¢ã»ã³ããªã¯ãJSãCSSãããã³HTMLãã¡ã€ã«ã®çž®å°ãåæãšããŠããŸãã
ãã©ã°
--no-cacheã¯ããªãœãŒã¹ãã£ãã·ã¥ãç¡å¹ã«ããããšãæå³ããŸãããã£ãã·ã³ã°ã«ããããããžã§ã¯ãã®æ§ç¯ãšåæ§ç¯ããªã¢ã«ã¿ã€ã ã§é«éã«è¡ãããšãã§ããŸããããã¯éçºæã«ã¯é¢ä¿ããããŸããã宿åãçµã¿ç«ãŠããšãã«ã¯ããŸãé¢ä¿ãããŸããã
ãã1ã€ã®ãã€ã³ãïŒããã©ã«ãã§ã¯ãParcelã¯çæããããã¡ã€ã«ãdistãã©ã«ããŒã«é 眮ããŸããdistãã©ã«ããŒã¯ãæ¬ èœããŠããå Žåã«äœæãããŸããåé¡ã¯ãåæ§ç¯æã«å€ããã¡ã€ã«ãåé€ãããªãããšã§ãããã®ãããªãã¡ã€ã«ãåé€ããã«ã¯ãparcel-plugin-clean-easyãªã©ã®ç¹å¥ãªãã©ã°ã€ã³ãå¿ èŠã§ãã
ã䜿çšããŠãã®ãã©ã°ã€ã³ãã€ã³ã¹ããŒã«ããŸã
npm i parcel-plugin-clean-easy -D ãããŠãpackage.jsonã«ä»¥äžã远å ããŸãã
"parcelCleanPaths": [
"dist",
".cache"
]
parcelCleanPathsã¯ãåæ§ç¯æã«åé€ããããã£ã¬ã¯ããªã§ãã
ããã§ãããŒã»ã«ãå®å šã«æ§æãããŸãããã¿ãŒããã«ãéãããšå ¥åããŠ
npm run devãEnterããŒãæŒããŸãã
Parcelã¯ãããžã§ã¯ããéçºã¢ãŒãã§ãã«ãããããŒã«ã«ãµãŒããŒãèµ·åããŠããã©ãŠã¶ãŒã§ã¢ããªã±ãŒã·ã§ã³ãéããŸããåªããã
ããã§ã¯ãå¶äœçšã®ãããžã§ã¯ãããŸãšããŠã¿ãŸãããã
ã³ãã³ããå®è¡ã
npm run proãŸãã
ãã©ãŠã¶ã§ã¢ããªã±ãŒã·ã§ã³ãèµ·åããŸãã
ãã£ãšãäœããããŸããããªãã£ãããã§ãã
çæãããindex.htmlãèŠãŠã¿ãŸããããããã«ã¯äœãèŠããŸããïŒãã³ãïŒãªã³ã¯ã¿ã°ãšã¹ã¯ãªããã¿ã°ã®ãã¹ã«æ³šæããŠãã ãããäœã«æ¥ç¶ãããŠããã®ãæ£ç¢ºã«ã¯ããããŸããããParcelã¯çžå¯Ÿãªã³ã¯ãã/ path-to-fileãã«å€æãããã©ãŠã¶ã¯ãã®ãããªãªã³ã¯ãèªã¿åããŸããã
ãã®åé¡ã解決ããã«ã¯ããproãã¹ã¯ãªããã«ã--public-urlãããã©ã°ã远å ããå¿ èŠããããŸãã
åæ§ç¯ãéå§ããŸãã
çžå¯Ÿãã¹ã¯æ£ãããã¢ããªã±ãŒã·ã§ã³ã¯æ©èœããŸããæ¶Œããã
ç§ã«ãšã£ãŠã¯ããã§ãã¹ãŠã§ããæž èŽããããšãããããŸããã