This post is more or less a follow up of this post I made in November 2017:
The app, or at least a MVP of it, is now alive and kicking (with its flaws) and it has been in production for week now.
In the previous post I was asking a lot of questions, in this one I will try to provide some answers. Bear in mind that a couple of months of me doing "modern" frontend development do not an expert make :D.
Unfortunately I can't disclose many details about the "what" but it's pretty much a web app to publish static HTML pages on AWS S3. The (company) user inputs data, some magic happen and the customer on its mobile app sees the mini website inside a mobile app. Nothing glorious but there are some moving parts and more will appear in the future that are going to be controlled or integrated in the app itself, which now are handled by separate tools or apps.
In the previous post, after ingesting an insane amount of content on the web, which got me definitely confused, I had asked if the app should have been a SPA. I'm here to tell you that my first and only SPA is working :-)
Generally speaking it's a SPA built with VueJS and whose backend is a Python/Flask web server.
Both parts live in the same repository, they just are in two separate directories:
$ ls -1 */
In development mode the frontend talks to the backend using webpack's DevServer proxy, in production the frontend is built in the
frontend/dist folder which the backend knows to serve as its static folder.
I'm not sure the latter is the greatest idea but for now it's working well, though sometimes I'm tempted to move the frontend inside the backend because they are technically the same app. I haven't decided yet.
Everything is deployed on Heroku.
I gravitated towards Vue probably for the same reason I gravitated towards Python many years ago: I don't like complicated things. I like simple technologies that can handle complexity. React didn't attract me much (I have a thing for the underdogs, in life too :D), JSX didn't make sense to me and I fell in love with the "Single File Component" style in Vue and I was sure it could do everything I needed.
After some trial and error I created my
frontend folder the right way using
vue "webpack" template.
This template does all you need: sets up the basic app structure, the basic commands, configures babel and its plugins, eslint, all the webpack build tooling, integration with the backend is super easy to setup, and it also sets up unit and e2e testing.
You just need to work with it and not against it especially if, like me, you balk at the amount of generated code when you first create the app. Generated code you have no idea what it is there for. I hope Webpack 4 and the zero configuration approach will improve things in this department in the future.
First and foremost I was trying to decide which UI framework to use. Vue has so many and it's not very easy for a newcomer to decide. The client giving me total technology freedom didn't really help (constraints are useful). My final indecision was between Boostrap Vue and Buefy, a framework based on CSS framework Bulma.
I honestly chose Buefy because my eyes were tired of seeing photocopied Bootstrap-based websites (including my own) and not being the frontend artist I could be I choose the novelty. Not very rational of me but don't worry, I checked if the project was alive and if they had the main components I needed.
The other UI libraries I'm using are mdi for Buefy's Material Design Icons, uppy which is an amazing file uploader, v-clipboard to copy text to the user's clipboard, vee-validate for form validation, vue-color for color pickers.
Last but not least: vue-router to handle routing in the frontend.
As you can imagine it's not the most nimble of apps but it's an internal one, it's used only on the desktop and I'm not optimising anything right now, just building and learning :-)
Apart from VSCode and the obvious webpack I'm using other tools:
eslint and stylelint are helping keeping the code clean. For JS I use an airbnb style with semi colons but you can also choose "standard" during the initial template creation. For CSS I use both CSS and SASS/SCSS so stylelint knows about the latter.
This is the
scripts section of my
"analyze": "webpack --config build/webpack.prod.conf.js --profile --json > /tmp/stats.json && webpack-bundle-analyzer /tmp/stats.json",
"build": "node build/build.js",
"dev": "SERVER_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"e2e": "node test/e2e/runner.js",
"lint-css": "stylelint 'src/**/*.vue'",
"lint-fix": "yarn run lint-js-fix",
"lint-js-fix": "eslint --report-unused-disable-directives --color --ext .js,.vue src test/unit/specs test/e2e/specs --fix",
"lint-js": "eslint --report-unused-disable-directives --color --ext .js,.vue src test/unit/specs test/e2e/specs",
"lint": "yarn run lint-css && yarn run lint-js",
"start-dashboard": "SERVER_ENV=development webpack-dashboard -- webpack-dev-server --config build/webpack.dev.conf.js",
"start": "yarn run dev",
"test": "yarn run unit",
"unit": "jest --config test/unit/jest.conf.js --coverage"
Some have been setup by the template, some are mine, some like
start-dashboard I'm not sure why are still there :-D
If you are still with me I would like to share a few general things I've learned:
Webpack it's not the easiest thing to configure. Sometimes you end up reading comments on issues on Github to see how to solve this or that thing.
Modern frontend development is definitely easier than in the past. Yes, learning Vue has a bit of a learning curve but the tooling it's amazing and webpack's hot reloader is magic (I really have no idea how all this stuff works and I'm not 100% sure I care)
Modern frontend development is faster for the developer. You introduce a bug, fix it in the editor, press ⌘-tab and the fix it's already there on the page (VSCode is configured to save upon loss of focus). Same thing for the interactions with the backend: I save a form in the frontend, the backend breaks because it has a bug in some function, I write the server side unit test, fix the code, press save again on the frontend and that's it. No refreshing, no re-inputing data in the form, no nothing.
Building reusable components in Vue is super easy: you basically just need to accept a
valueand emit an
inputevent and you can send data from the child to the parent using v-model. I'll talk about it more in a future article.
I still haven't mastered code reuse in Vue. I have a few reusable components, a few mix-ins (mainly for validation) but I still have a lot of code duplication between the various components. I'm not worried, I'm sure it's going to disappear the more I learn (especially about slots)
I still haven't understood how nested routes work. My routes now are all logically flat inside the router, just the paths are nested.
I'm not using vuex. It's not like I don't know what it is for and I'll probably need it at some point but for now each component has its own state, the reusable ones talk to their parent using
v-modeland the main components state come from the backend on creation. Each component it's responsible for initialising itself, either through its own state (think about the "create new something" form) or through an API call.
I honestly think it would have taken me more time to ship this app if I had gone the "safe and paved way" without Vue.
I'm going to stop here because this article is already pretty long. I haven't talked about reusable components, tests and the backend. Expect more articles in the future :D