Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scaffolding a Progressive Web App using Vue CLI 3 | webclerks

Scaffolding a Progressive Web App using Vue CLI 3 | webclerks

Vue CLI 3 has been released and it’s completely different from its previous version. Discover how it simplifies your toolchain, reduces configuration fatigue and improves your developer experience.

https://manu.ninja/scaffolding-a-progressive-web-app-using-vue-cli-3

Manuel Wieser

November 14, 2018
Tweet

More Decks by Manuel Wieser

Other Decks in Programming

Transcript

  1. Manuel Wieser | @manuelwieser | manu.ninja Manuel Wieser Lead Web

    Developer karriere.at Lecturer Hypermedia User Experience Engineering FH OÖ Campus Hagenberg @manuelwieser manu.ninja
  2. Topics Vue? Vue CLI? Installation Instant Prototyping Creating a Project

    What’s in a Project? Vue CLI Plugins Configuration Building
  3. Vue CLI is a tool for scaffolding Vue projects full

    system for rapid Vue development
  4. Manuel Wieser | @manuelwieser | manu.ninja Installation npm uninstall -g

    vue-cli npm install -g @vue/cli vue --version vue --help
  5. Manuel Wieser | @manuelwieser | manu.ninja Instant Prototyping npm install

    -g @vue/cli-service-global echo "<template>\ <h1>Hello webclerks\!</h1>\ </template>" > App.vue vue serve
  6. Manuel Wieser | @manuelwieser | manu.ninja • vue serve uses

    the same default setup (webpack, Babel, PostCSS, ESLint) as projects created by vue create • Entry can be main.js, index.js, App.vue or app.vue … • You can provide an index.html, package.json, use local dependencies, or add config files for Babel, PostCSS and ESLint Instant Prototyping
  7. Instant Prototyping <template> <Greeting :message="message"/> </template> <script> import Greeting from

    './Greeting.vue'; export default { data() { return { message: Hello webclerks!' } }, components: { Greeting } }; </script> <template> <h1>{{ message }}</h1> </template> <script> export default { props: ['message'] } </script> Greeting.vue App.vue
  8. Manuel Wieser | @manuelwieser | manu.ninja Instant Prototyping vue build

    dist ├── index.html └── js ├── app.fbe6ce0a.js ├── app.fbe6ce0a.js.map ├── chunk-vendors.aa4f98a5.js └── chunk-vendors.aa4f98a5.js.map
  9. Manuel Wieser | @manuelwieser | manu.ninja Creating a Project vue

    create my-project npm install -g @vue/cli-init vue init webpack my-project # [email protected] vue ui
  10. Presets { "useConfigFiles": false, "plugins": { "@vue/cli-plugin-babel": {}, "@vue/cli-plugin-eslint": {

    "config": "airbnb", "lintOn": ["save", "commit"] } }, // … // … "router": true, "routerHistoryMode": true, "vuex": true, "cssPreprocessor": "sass" } }
  11. Manuel Wieser | @manuelwieser | manu.ninja Presets vue config vue

    create --preset my-preset my-project # --preset my-user/my-repository # --preset my-preset.json
  12. Manuel Wieser | @manuelwieser | manu.ninja What’s in a Project?

    ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src ├── App.vue ├── assets │ └── logo.png ├── components │ └── HelloWorld.vue └── main.js
  13. Manuel Wieser | @manuelwieser | manu.ninja Vue CLI Plugins "dependencies":

    { "vue": "^2.5.17" }, "devDependencies": { "@vue/cli-plugin-babel": "^3.0.3", "@vue/cli-plugin-eslint": "^3.0.3", "@vue/cli-service": "^3.0.3", "vue-template-compiler": "^2.5.17" }
  14. Manuel Wieser | @manuelwieser | manu.ninja CLI Service "scripts": {

    "serve": "vue-cli-service serve", "build": "vue-cli-service build" } npx vue-cli-service help
  15. Configuration "eslintConfig": {...}, "postcss": {...}, "browserslist": [ "> 1%", "last

    2 versions", "not ie <= 8" ] module.exports = { presets: [ '@vue/app', ], }; package.json babel.config.js
  16. Manuel Wieser | @manuelwieser | manu.ninja Plugins vue add @vue/pwa

    # @vue/cli-plugin-pwa vue ui vue add apollo # vue-cli-plugin-apollo
  17. Manuel Wieser | @manuelwieser | manu.ninja Changes? ├── package-lock.json ├──

    package.json ├── public │ ├── img │ │ └── icons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── ... │ ├── manifest.json │ └── robots.txt └── src ├── main.js └── registerServiceWorker.js
  18. Configuration module.exports = { pwa: { name: 'Japanese Phrasebook', themeColor:

    '#f44336', msTileColor: '#f44336', workboxOptions: {...} } }; cacheId: 'phrasebook', importWorkboxFrom: 'local', navigateFallback: 'shell.html', navigateFallbackWhitelist: [/^((?!\/404).)*$/] vue.config.js workboxOptions
  19. Official Plugins • @vue/cli-plugin-babel • @vue/cli-plugin-typescript • @vue/cli-plugin-eslint • @vue/cli-plugin-pwa

    • @vue/cli-plugin-unit-jest • @vue/cli-plugin-unit-mocha • @vue/cli-plugin-e2e-cypress • @vue/cli-plugin-e2e-nightwatch
  20. Manuel Wieser | @manuelwieser | manu.ninja HTML • public/index.html is

    processed with html-webpack-plugin ◦ Variables (<link rel="icon" href="<%= BASE_URL %>favicon.ico">) ◦ JavaScript/CSS ◦ preload/prefetch hints (@vue/preload-webpack-plugin) ◦ manifest/icon links (@vue/cli-plugin-pwa) • Multi-Page Application ◦ pages option in vue.config.js
  21. Manuel Wieser | @manuelwieser | manu.ninja CSS • Preprocessors are

    preconfigured, you just have to install the webpack loaders (hasn’t changed from Vue CLI 2) ◦ npm install -D sass-loader node-sass • PostCSS ◦ Can be configured via any of its configuration file options or css.loaderOptions.postcss in vue.config.js • Support for CSS Modules
  22. Manuel Wieser | @manuelwieser | manu.ninja webpack Configuration • vue.config.js

    • configureWebpack option is merged using webpack-merge • chainWebpack option allows total control via webpack-chain
  23. Manuel Wieser | @manuelwieser | manu.ninja webpack Configuration module.exports =

    { configureWebpack: { plugins: [ new MyPlugin() ], } }; vue.config.js
  24. Manuel Wieser | @manuelwieser | manu.ninja webpack Configuration module.exports =

    { configureWebpack: config => { if (process.env.NODE_ENV === 'production') { // You can mutate the config directly … } // … or return an object which will be merged. } };
  25. Manuel Wieser | @manuelwieser | manu.ninja webpack Configuration module.exports =

    { chainWebpack: config => { config .plugin('html') .tap(args => { return [/* … */] }) } };
  26. Manuel Wieser | @manuelwieser | manu.ninja Assets • Relative Path

    Imports ◦ JavaScript/CSS imports, HTML/CSS references ◦ file-loader/url-loader ◦ Assets Images < 4 KB are inlined ◦ Filenames include content hashes (for cache-busting) • public Folder ◦ You may have to prefix your links with <%= BASE_URL %>
  27. Manuel Wieser | @manuelwieser | manu.ninja Assets <img src="./assets/logo.svg" alt="Logo">

    <!-- becomes --> <img src="./assets/logo.ec9a16c8.svg" alt="Logo"> <img src="./assets/logo.svg" alt="Logo"> <!-- becomes (after modifying default config) --> <img src="data:image/svg+xml;base64,..." alt="Logo">
  28. Manuel Wieser | @manuelwieser | manu.ninja webpack Inspection • You

    can print the resolved webpack config for inspection ◦ vue inspect ◦ vue inspect --help • You can use the resolved webpack config as a file (for IDEs or CLI tools) ◦ <projectRoot>/node_modules/@vue/cli-service/webpack.config.js
  29. Manuel Wieser | @manuelwieser | manu.ninja webpack Configuration module.exports =

    { chainWebpack: (config) => { config.module.rules.delete('svg'); config.module.rule('images') .test(/\.(svg|png|jpe?g|gif|webp)(\?.*)?$/); }, }; vue.config.js
  30. Manuel Wieser | @manuelwieser | manu.ninja Browser Compatibility • package.json

    (browserlist) or .browserlistrc • @babel/preset-env and PostCSS’ autoprefixer • Polyfills are automatically chosen (per default) • “Modern Mode”
  31. Manuel Wieser | @manuelwieser | manu.ninja Browser Compatibility vue-cli-service build

    --modern dist/js ├── [5.2K] app-legacy.3a1db1b0.js ├── [5.1K] app.053009ed.js ├── [ 80K] chunk-vendors-legacy.bb3a6f6d.js ├── [ 63K] chunk-vendors.c571e522.js
  32. Manuel Wieser | @manuelwieser | manu.ninja Browser Compatibility <head> <link

    href=/js/app.8c81428a.js rel=modulepreload as=script> <link href=/js/chunk-vendors.78830d76.js rel=modulepreload as=script> </head> <body> <script type=module src=/js/chunk-vendors.78830d76.js></script> <script type=module src=/js/app.8c81428a.js></script> <script src=/js/chunk-vendors-legacy.c19c13a2.js nomodule></script> <script src=/js/app-legacy.243e8169.js nomodule></script> </body>
  33. Manuel Wieser | @manuelwieser | manu.ninja Build Targets • App

    • Library ◦ Vue is externalized, falls back to global Vue if it can’t be resolved through the bundler ◦ CommonJS, UMD, ES Modules (not yet) • Web Component ◦ Vue is externalized, assumes global Vue is available on the host page ◦ Single JavaScript file (everything inlined) that registers a custom element
  34. Manuel Wieser | @manuelwieser | manu.ninja Build Targets vue build

    --target wc --name my-footer 'src/components/Footer.vue' dist/my-footer.min.js 16.55 kb 7.53 kb dist/my-footer.js 43.70 kb 12.46 kb <script src="https://unpkg.com/vue"></script> <script src="./my-footer.js"></script> <my-footer></my-footer>
  35. Vue CLI 3 Official plugins for Babel, TypeScript, ESLint, PostCSS,

    PWAs, Unit Testing and E2E Testing Compose your project out of plugins instead of selecting from a few pre-defined templates No need to “eject”, so your project can benefit from bugfixes and updates to plugins Fancy GUI Instant Prototyping Ship your code as native ES2015+ or convert your Vue components to Web Components
  36. Manuel Wieser | @manuelwieser | manu.ninja Official Documentation • Vue

    CLI 3 Guide • Vue CLI 3 Configuration Reference • Vue CLI 3 Plugin Development Guide