michael@CoalitionToAbolishPoverty.org
GET URL: server process
GET URL: file
Dynamic Page (PHP, Nuxt Universal)
Static Page (jQuery)
<html>
<body>
stuff
</body>
</html>
Serve content from files.
Apache, Nginx
<html>
<body>
<?php echo "stuff"; ?>
</body>
</html>
Serve content from URL, templates, and cookies.
CGI, PHP, Ruby on Rails, WordPress
Dynamic Page (PHP, Nuxt Universal)
Single Page App (Nuxt SPA)
Static Site Gen (Github pages)
Static Page (jQuery)
GET URL: server process
Click 'page': browser
GET URL: file
Click 'page': file
<html>
<body>
<a ui-sref="stuff">x</a>
</body>
</html>
One HTML for all URLS. Browser routes "pages".
Angular + ui-router, Backbone, Ember, Vue
index.html
blog/hello.html
blog/post-more-often.html
about-us/index.html
contact/index.html
Prerender HTML for each URL w/ declarative content.
Jekyll, Wintersmith, Hexo, Github pages, Nuxt
Dynamic Page (PHP, Nuxt Universal)
Single Page App (Nuxt SPA)
Static Site Gen (Github pages)
Static Page (jQuery)
GET URL: server process
Click 'page': browser
GET URL: file
Click 'page': file
Dynamic Page (PHP, Nuxt Universal)
Single Page App (Nuxt SPA)
Static Site Gen (Github pages)
Static Page (jQuery)
GET URL: server process
Click 'page': browser
! Not SEO friendly !
GET URL: file
Click 'page': file
! Not an App !
By default, Vue components produce and manipulate DOM in the browser as output.
However, it is also possible to:
This is a Vue.js feature:
Statically Generated SPA (Nuxt Static Site)
Progressive Web App (Offline, Nuxt PWA)
GET URL: file
Click page: browser
"Hydrate": REST (asyncData)
Dynamic Page (PHP, Nuxt Universal)
Single Page App (Nuxt SPA)
Static Site Gen (Github pages)
Static Page (jQuery)
Then:
code & content
/layouts
/pages
/assets
/components
/plugins
Nuxt Universal App (Express)
/.nuxt/index.js
Static Site
/index.html
/pages/index.html
/_nuxt/*
(aka Server Rendered Deployment) (aka Nuxt Universal)
// ------------------------- Dev:
nuxt
// or
npm run dev
// ------------------------- Production:
// compile to .nuxt directory
nuxt build
// run web server with Node.js
nuxt start
nuxt build -> .nuxt
GET page: server process
Click page: browser
// ------------------------- Dev:
nuxt || npm run dev
// ------------------------- Production:
// compile static site to dist directory
nuxt generate
// Push files to web server...
nuxt_deploy_or_whatever.sh
(aka Server Generated Deployment) (pre-rendered) (static site)
nuxt generate -> dist
GET page: file
Click page: browser
"Hydrate": REST (asyncData)
Laptop:
`nuxt generate`
?
Cloud:
?
Laptop:
`nuxt generate`
Why Cloud?
Why AWS?
I already have an account.
Gulp code from wintersmith project
SSL
CDN
Browser
S3 bucket
CloudFront
npm run deploy
nuxt generate
deploy.sh
gulp
AWS
Laptop
SSL
CDN
Browser
S3 bucket
CloudFront
Stores files
Static website hosting
http://coalitiontoabolishpoverty.org.s3-website-us-east-1.amazonaws.com
Content Delivery Network
Certificate Manager
"Invalidate" cache to refresh from S3.
https://coalitiontoabolishpoverty.org
SSL
CDN
Browser
S3 bucket
CloudFront
Setup AWS stuff:
1. S3 bucket
2. CloudFront -> S3
3. DNS -> CloudFront
4. Securely push files -> S3
Deploy our stuff:
1. Push files -> S3
2. Invalidate CloudFront to refresh from S3
Setup AWS stuff:
1. S3 bucket
2. CloudFront -> S3
3. DNS -> CloudFront
4. Securely push files -> S3
SSL
CDN
Browser
S3 bucket
CloudFront
Read the Nuxt FAQ
AWS Console tour
SSL
CDN
Browser
S3 bucket
CloudFront
Setup AWS stuff:
1. S3 bucket
2. CloudFront -> S3
3. DNS -> CloudFront
4. Securely push files -> S3
We need this data:
Read the Nuxt FAQ
SSL
CDN
Browser
S3 bucket
CloudFront
Deploy our stuff:
1. Push files -> S3
2. Invalidate CloudFront to refresh cache
(see new content right away)
gulp - streaming build system w/o a webpack PhD
Problem solved w/ NPM packages:
SSL
CDN
Browser
S3 bucket
CloudFront
Deploy our stuff:
1. deploy.sh
2. .gitignore
3. packages!
4. gulpfile.js
5. Deploy already!
#!/bin/bash
export AWS_ACCESS_KEY_ID="key"
export AWS_SECRET_ACCESS_KEY="secret"
export AWS_BUCKET_NAME="example.com"
export AWS_CLOUDFRONT="UPPERCASE"
# If nvm (node version manager),
[ -s "$HOME/.nvm/nvm.sh" ] \
&& source "$HOME/.nvm/nvm.sh" \
&& nvm use
# Npm install if not already.
[ ! -d "node_modules" ] && npm install
nuxt generate
gulp deploy
# or configure package.json scripts
npm run generate
npm run deploy
Deploy our stuff:
1. deploy.sh
2. .gitignore
3. packages!
4. gulpfile.js
5. Deploy already!
$ chmod +x deploy.sh
$ echo "
# Don't commit build files
node_modules
dist
.nuxt
.awspublish
deploy.sh
" >> .gitignore
Deploy our stuff:
1. deploy.sh
2. .gitignore
3. packages!
4. gulpfile.js
5. Deploy already!
$ npm install --save-dev \
gulp \
gulp-awspublish \
gulp-cloudfront-invalidate-aws-publish \
concurrent-transform
$ npm install -g gulp
4. gulpfile.js
var gulp = require('gulp');
var awspublish = require('gulp-awspublish');
var cloudfront = require('gulp-cloudfront-invalidate-aws-publish');
var parallelize = require('concurrent-transform');
// https://docs.aws.amazon.com/cli/latest/userguide/cli-environment.html
var config = {
// Required
params: { Bucket: process.env.AWS_BUCKET_NAME },
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
// Optional
deleteOldVersions: false, // NOT FOR PRODUCTION
distribution: process.env.AWS_CLOUDFRONT, // CloudFront distribution ID
region: process.env.AWS_DEFAULT_REGION,
headers: { /*'Cache-Control': 'max-age=315360000, no-transform, public',*/ },
// Sensible Defaults - gitignore these Files and Dirs
distDir: 'dist',
indexRootPath: true,
cacheFileName: '.awspublish',
concurrentUploads: 10,
wait: true, // wait for CloudFront invalidation to complete (about 30-60 seconds)
}
gulp.task('deploy', function() {
// create a new publisher using S3 options
// http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property
var publisher = awspublish.create(config, config);
// Collect all the files in distDir
var g = gulp.src('./' + config.distDir + '/**');
// Send those files through publish.
g = g.pipe(parallelize(publisher.publish(config.headers), config.concurrentUploads))
// Invalidate distribution cache so new content appears
if (config.distribution) {
console.log('Configured with CloudFront distribution');
g = g.pipe(cloudfront(config));
} else {
console.log('No CloudFront distribution configured - skipping CDN invalidation');
}
// Delete removed files - breaks older versions being viewed
if (config.deleteOldVersions) g = g.pipe(publisher.sync());
// create a local cache of files to speed up consecutive uploads
g = g.pipe(publisher.cache());
// print upload updates to console
g = g.pipe(awspublish.reporter());
return g;
});
$ ./deploy.sh
Found '/home/michael/scm/example.com/www/.nvmrc' with version <8>
Now using node v8.11.2 (npm v5.6.0)
> example.com@1.0.0 generate /home/michael/scm/example.com/www
> nuxt generate
nuxt:generate Generating... +0ms
nuxt:build App root: /home/michael/scm/example.com/www +0ms
nuxt:build Generating /home/michael/scm/example.com/www/.nuxt files... +0ms
nuxt:build Generating files... +36ms
nuxt:build Generating routes... +10ms
nuxt:build Building files... +24ms
████████████████████ 100%
Build completed in 7.009s
DONE Compiled successfully in 7013ms 21:25:22
Hash: 421d017116d2d95dd1e3
Version: webpack 3.12.0
Time: 7013ms
Asset Size Chunks Chunk Names
pages/index.ef923f795c1cecc9a444.js 10.6 kB 0 [emitted] pages/index
layouts/default.87a49937c330bdd31953.js 2.69 kB 1 [emitted] layouts/default
pages/our-values.f60c731d5c3081769fd9.js 3.03 kB 2 [emitted] pages/our-values
pages/join-us.835077c4e6b55ed1bba4.js 1.3 kB 3 [emitted] pages/join-us
pages/how.75f8cb5bc24e38bca3b3.js 2.59 kB 4 [emitted] pages/how
app.6dbffe6ac4383bd30a92.js 202 kB 5 [emitted] app
vendor.134043c361c9ad199c6d.js 6.31 kB 6 [emitted] vendor
manifest.421d017116d2d95dd1e3.js 1.59 kB 7 [emitted] manifest
+ 3 hidden assets
Hash: 9fd206f4b4e571e9571f
Version: webpack 3.12.0
Time: 2239ms
Asset Size Chunks Chunk Names
server-bundle.json 306 kB [emitted]
nuxt: Call generate:distRemoved hooks (1) +0ms
nuxt:generate Destination folder cleaned +10s
nuxt: Call generate:distCopied hooks (1) +8ms
nuxt:generate Static & build files copied +7ms
nuxt:render Rendering url /our-values +0ms
nuxt:render Rendering url /how +67ms
nuxt:render Rendering url /join-us +1ms
nuxt:render Rendering url / +0ms
nuxt: Call generate:page hooks (1) +913ms
nuxt: Call generate:page hooks (1) +205ms
nuxt: Call generate:page hooks (1) +329ms
nuxt: Call generate:page hooks (1) +361ms
nuxt:generate Generate file: /our-values/index.html +2s
nuxt:generate Generate file: /how/index.html +0ms
nuxt:generate Generate file: /join-us/index.html +0ms
nuxt:generate Generate file: /index.html +0ms
nuxt:render Rendering url / +2s
nuxt: Call generate:done hooks (1) +4ms
nuxt:generate HTML Files generated in 11.8s +5ms
nuxt:generate Generate done +0ms
[21:25:27] Using gulpfile ~/scm/example.com/www/gulpfile.js
[21:25:27] Starting 'deploy'...
Configured with CloudFront distribution
[21:25:27] [cache] README.md
[21:25:27] [cache] android-chrome-192x192.png
[21:25:27] [cache] android-chrome-512x512.png
[21:25:27] [cache] apple-touch-icon.png
[21:25:27] [cache] browserconfig.xml
[21:25:27] [cache] favicon-16x16.png
[21:25:27] [cache] favicon-32x32.png
[21:25:27] [cache] favicon.ico
[21:25:27] [cache] favicon.svg
[21:25:27] [cache] logo-branches.svg
[21:25:27] [cache] logo-small.svg
[21:25:27] [cache] logo.svg
[21:25:27] [cache] mstile-150x150.png
[21:25:27] [cache] og-image.jpg
[21:25:27] [cache] safari-pinned-tab.svg
[21:25:27] [cache] site.webmanifest
[21:25:28] [create] _nuxt/manifest.421d017116d2d95dd1e3.js
[21:25:29] [update] 200.html
[21:25:30] [create] videos/flag.jpg
[21:25:30] [create] _nuxt/vendor.134043c361c9ad199c6d.js
[21:25:34] [create] videos/flag.mp4
[21:25:34] [cache] _nuxt/pages/how.75f8cb5bc24e38bca3b3.js
[21:25:34] [cache] _nuxt/pages/join-us.835077c4e6b55ed1bba4.js
[21:25:34] [cache] _nuxt/pages/our-values.f60c731d5c3081769fd9.js
[21:25:36] [update] our-values/index.html
[21:25:36] [create] _nuxt/layouts/default.87a49937c330bdd31953.js
[21:25:36] [create] _nuxt/app.6dbffe6ac4383bd30a92.js
[21:25:37] [create] _nuxt/pages/index.ef923f795c1cecc9a444.js
[21:25:38] [update] join-us/index.html
[21:25:38] [update] how/index.html
[21:25:43] [create] videos/flag.webm
[21:25:43] [update] index.html
[21:25:43] CloudFront invalidation created: I16NXXXXX4JDOA
[21:26:09] Finished 'deploy' after 42 s
5. Deploy Already!