strategy builder: frontend build
assumptions:
- you know what github and javascript/Vue is
- you know a bit about how Node/yarn works
- you know/don't care about all the specifics of how webpack works
- you don’t know how frontend stuff is built/runs
topics:
- vue-build-system and what's in it
- things that are magic (webpack)
- design-system and how to connect
- third party libraries (axios, brace, draggable)
- brief overview of testing (maybe)
vue-build-system
what is it?
- An Infusionsoft github repo that contains shared webpack and build configurations.
- https://github.com/infusionsoft/vue-build-system
- When you run yarn dev in build system, you are running the dev-server configuration from the vue-build-system.
- Package.json:
"scripts": {
"dev": "node build/dev-server.js",
...
}
build/dev-server
The infusionsoft dev-server does most of the heavy lifting. It provides us:
- Express app server
- Wiring in of webpack
- Hot reloading middleware
You can view it here: https://github.com/infusionsoft/vue-build-system/blob/master/build/dev-server.js
const server = require('@infusionsoft/vue-build-system/build/dev-server.js');
const webpackConfig = require('./webpack.dev.config');
server.start(webpackConfig, 10229);
build/webpack.dev.config:
Infusionsoft’s webpack.dev.config pulls in the base config and then adds to it, enabling:
-
Source Maps
-
CDN wiring for webpack
-
Friendly errors plugin
const merge = require('webpack-merge');
const cdnOptions = require('./cdn');
const sharedDevWebpack = require('@infusionsoft/vue-build-system/build/webpack.dev.config')(cdnOptions);
const baseWebpack = require('./webpack.base.config');
module.exports = merge(sharedDevWebpack, baseWebpack);
The @infusionsoft/vue-build-system also handles:
-
Minifying/compressing code in prod
-
Vue and scss file compiling
-
Some eslinting
-
process.env.NODE_ENV js variable
vue-build-system - TL;DR:
- It's what handles most of the stuff that runs when you run yarn dev
- Contains things that you need to set up once when you start and then never touch
- Cons: if it breaks it's hard to find out why
- Pros: everyone is using it so it's everyone's problem
webpack
webpack
- A popular third-party bundler/builder
- takes all of your frontend assets (.vue files, .js files, images, .sass files, everything) and bundles them in a way that the browser can read and understand.
- It also handles magical things like hot reloading.
Pros
- It’s super powerful and solves all your bundling needs
- There’s basically no competitors
Cons
- There’s basically no competitors
- It’s huge, and hard to understand re: magic
- When it breaks it’s hard to debug (but there’s almost definitely something wrong with your config file(s)…
- we have config files several in different places.
Important webpack things
- Aliases
- CDN
- Minify
Aliases
Shortcut for the base location of where to find import definitions.
// build/webpack.base.config
const path = require('path');
module.exports = {
resolve: {
alias: {
app: path.resolve('./src/app'),
...
},
},
...
};
then in your component...
import Component from 'app/components/Component';
CDN
- “Content Delivery Network”
- A place to put external resources (things you know will be needed by everyone using your project - example: Vue framework, vuex) and are easily cached/not going to be changed any time soon.
- You put links to js files that are hosted on a CDN in webpack’s cdn configs, and make sure you mark them as “external” so webpack doesn’t try to package them with your app js files.
CDN
Remember in build?
// build/webpack.dev.config.js
const merge = require('webpack-merge');
const cdnOptions = require('./cdn');
const sharedDevWebpack = require('@infusionsoft/vue-build-system/build/webpack.dev.config')(cdnOptions);
const baseWebpack = require('./webpack.base.config');
module.exports = merge(sharedDevWebpack, baseWebpack);
CDN
// build/cdn.js
const path = require('path');
// get version from package.json
const version = (name) => {
return require(path.join(__dirname, '../node_modules', name, 'package.json')).version;
};
// if in dev don't get the minified version
const min = process.env.NODE_ENV !== 'dev';
const minCheck = min ? '.min' : '';
// using unpkg.com for cdn; this is usually reliable
const cdnjs = [
`//unpkg.com/vue@${version('vue')}/dist/vue${minCheck}.js`,
`//unpkg.com/vuex@${version('vuex')}/dist/vuex${minCheck}.js`,
`//unpkg.com/vue-router@${version('vue-router')}/dist/vue-router${minCheck}.js`,
`//unpkg.com/vue-i18n@${version('vue-i18n')}/dist/vue-i18n${minCheck}.js`,
`//unpkg.com/moment@${version('moment')}/min/moment-with-locales${minCheck}.js`,
];
const cdncss = [];
module.exports = {
cdnjs,
cdncss,
externals: {
vue: 'Vue',
vuex: 'Vuex',
'vue-router': 'VueRouter',
'vue-i18n': 'VueI18n',
moment: 'moment',
},
};
If you want to externalize a script, you would do it here
Hot Reloading
- the browser will reload source files that have been changed without you having to manually reload the page.
- IMO this is one of the best/most useful features of webpack but it can also be the most temperamental.
Minify
- Files should be minified/obfuscated in prod environments, to help with performance.
- Check out vue-build-system webpack configs to see this code in action
webpack - TL;DR:
- magic.gif
- it does all the build things
- there is a huge community
- use on big projects that use frameworks and have multiple environments
- hot reloading is the BEST
design-system
design-system
- For all your design assets that are shared across products.
- production link: https://infusionsoft.github.io/design-system
- Go to Product -> components to see all the different components
- Product -> Foundations has things like typography, colors, and icons.
How does it attach?
app/main.js
...
import Vue from 'vue';
const DesignSystem = require('@infusionsoft/design-system');
Vue.use(DesignSystem);
...
Now we have access to design system's
- vue components (like Icon and Editable)
- styles and sass vars (like $gp and $color-xxx)
- js vue functions (like $error and $toast)
Making changes
TEST your design-system changes with the web app
design-system> yarn dist:debug // builds js/css bundle
design-system> yarn link // creates a symlinkable folder for d-s
your-project> yarn link @infusionsoft/design-system
// symlinks to what was created
Your-project> yarn dev
You can look in node_modules/@infusionsoft/design-system to make sure your d-s changes are there
Then when you tweak d-s, run yarn dist:debug again and your changes should show up without having to restart your web server
Cutting a release
TL;DR:
- Use semver
- link to your PR in the notes of your release
- Once the release is out, update package.json with the new design-system version.
design-system TL;DR:
- It keeps things consistent across products
- Making updates/keeping updated can be a pain but it's worth it
third party libraries
// package.json
"dependencies": {
"@infusionsoft/design-system": "git+ssh://git@github.com/infusionsoft/design-system.git#~7.0.0",
"axios": "0.16.2",
"brace": "0.10.0",
"fastclick": "1.0.6",
"lodash.debounce": "4.0.8",
"moment": "2.18.1",
"vue": "2.5.9",
"vue-i18n": "7.0.4",
"vue-router": "2.7.0",
"vuedraggable": "^2.14.1",
"vuex": "3.0.1",
"vuex-persistedstate": "2.4.2"
},
Axios
- https://github.com/axios/axios
- Promise-based HTTP client for the browser. For your ajax convenience.
// app/main.js
...
import Vue from 'vue';
import axios from 'axios';
axios.defaults.headers.put['Content-Type'] = 'application/json;charset=UTF-8';
Vue.prototype.$http = axios;
...
Brace
- https://github.com/thlorenz/brace
- Browserify-compatible version of the Ace editor (syntax highlighter and formatter for code writing in the browser, currently used for HTML email writing)
FastClick
- https://labs.ft.com/fastclick/
- "FastClick is a simple, easy-to-use library for eliminating the 300ms delay between a physical tap and the firing of a click event on mobile browsers. The aim is to make your application feel less laggy and more responsive while avoiding any interference with your current logic."
// app/main.js
...
import FastClick from 'fastclick';
...
FastClick.attach(document.body);
Vue-draggable
- https://github.com/SortableJS/Vue.Draggable
- For drag & drop reordering of arrays.
// package.json
"dependencies": {
"@infusionsoft/design-system": "git+ssh://git@github.com/infusionsoft/design-system.git#~7.0.0",
"axios": "0.16.2",
"brace": "0.10.0",
"fastclick": "1.0.6",
"lodash.debounce": "4.0.8",
"moment": "2.18.1",
"vue": "2.5.9",
"vue-i18n": "7.0.4",
"vue-router": "2.7.0",
"vuedraggable": "^2.14.1",
"vuex": "3.0.1",
"vuex-persistedstate": "2.4.2"
},
strat builder package.json dependencies
Note: these are Dependencies and not
dev-dependencies, which are different.
TPL - TL;DR:
- Don't re-invent the wheel
- When you want to add a new one DEFINITELY let people know PLEASE - slack channel #dev-frontend
- The biggest problem with TPL is unknown breakages; Don't update the version without researching
- yarn lock is your friend
testing
Libraries used in frontend unit tests
- Mocha it's the test framework: the 'describe' and 'it' parts.
- Karma it runs the tests on a browser When you run npm test or yarn test, it's probably pointing to karma for running them.
-
Chai
it's the
expectation library. so in Chai you would say
- expect(myThing) .to.equal(thisThing).
- If you were using Jasmine (a different expectation library) you'd say expect(myThing) .toEqual(thisThing), like some kind of animal.
- Sinon the mocking / spying library. It's great for unit testing / stubbing out functions that you don't want to run, but you want to see if that function was called.
- vue-testing-utils Frameworks for mounting / shallow mounting vue components for testing.
How are the tests run?
-
README - how to run tests
-
look at test command in package.json
-
go to karma.config.js
-
files: index.js
Writing good frontend tests
There's a confluence page for that https://wiki.infusionsoft.com/display/PD/Write+Good+Frontend+Unit+Tests
TL;DR:
- use frontend unit tests to test component functionality individually
- Mocha/chai/sinon/karma combo of awesome
- vue-test-utils to test vue components
- Test troubleshooting found here: https://wiki.infusionsoft.com/display/PD/Write+Good+Frontend+Unit+Tests
Strategy builder - frontend
By Laurel Bruggeman
Strategy builder - frontend
brownbag for the frontend build of strategy builder
- 544