Web development notes
Modern web dev stuff I stumbled upon while working on a WYTIWYS (What You Tree Is What You Search) corpus query interface and a recipe website by and for programmers.
I learned the very, very basics of web development several years ago and didn’t like it very much. These are two projects that I approached with a strong intention to get things done, but no particular desire to learn anything new systematically. The Changing Stuff and Seeing What Happens approach worked to a surprising extent, and as I trial-and-errored my way through the code (and occasionally resorted to actually look up oddly specific stuff), I noted down random things I found remarkable, regretful, revolting, or (rarely) reasonable and even rewarding.
- Node commands and other useful command-line incantations
- CSS (Cursed Style Sheets)
- So-called TypeScript
- React
- Vue
Node commands and other useful command-line incantations
Setting up nvm (Node Version Manager)
- install
nvmfrom your package manager - add
. /usr/share/nvm/init-nvm.shto the shell config file.
Installing version n of Node
nvm install n
Using version n of Node
nvm use n
Installing a TypeScript project
npm install
Using a local module in a TypeScript project
- package the module into a
.tgz:npm pack - move to the project folder and install the package:
npm install --save PATH-TO-TGZ
Fixing npm error code EINTEGRITY upon npm install or similar
rm -rf package-lock.json node_modules
Generating TypeScript declaration files (.d.ts)
(also known as TypeScript definition files, for some reason)
For a single file:
tsc --declaration FILENAME.ts
For the entire project:
- ensure that the project’s
tsconfig.jsonhas"declaration": trueamong itscompilerOptions npm installtsc -p tsconfig.json
CSS (Cursed Style Sheets)
Hiding stuff
visibility: hiddenis like the invisibility cloak (the element becomes transparent, but still takes up space)display: noneprevents the element from showing up at all
Selectors
Basic selectors:
*tag.class#id[attribute]
Useful combinations:
tag.class(alltags of a given class).class tag(alltags that are descendants of a tag with a givenclass).class>tag(alltags that are direct descendants (children) of a tag with a givenclass)tag[attribute](alltags with a givenattribute).class1.class2(all elements that have bothclass1andclass2)
So-called TypeScript
(much of which also applies to JavaScript)
Array concatenation
Given
const a: number[] = [1, 2];
const b: number[] = [3, 4];
const c: number[] = [5];
-
spread operator:
const abc = [...a, ...b, ...c]; -
concatmethod:const abc = a.concat(b).concat(c);but also:
const abc = a.concat(b, c);and even:
const abc = a.concat(3, 4, 5); // wild!
Last element of an array
xs.slice(-1)[0]
Introspection
Two operators:
typeof xfor simple built-in types (boolean,number,string,object,function). It returns a lowercase string with the name of the typex instanceof Yfor custom types (classes) and complex built-in types, whatever they are (butArrayis one of them). The operands are an object and a class (not a string containing the name of the class!)
Examples:
typeof [] == 'object' // true
[] instanceof Object // true
[] instanceof Array // also true, because arrays are objects
typeof null == 'object' // true, but for no good reason at all
Integer to string and vice versa
int.toString();
parseInt(str, base);
Lambdas
(par1: type2, par2: type2): returnType => expression
JSON object operations
Kinda like a Python dictionary:
- does a
jsonobject have a certainkey?key in json - delete a
key-value pair from ajsonobject:delete json[key] - add a
key-valpair to ajsonobject:json[key] = val - iterate over all
key-valpairs (similar to Python dict items):for (const [key, value] of Object.entries(obj)) { // do whatever you need to do }
Ternary operator
I guess Javascript is a bit like Java:
condition ? what_if_true : what_if_not
Kind of the same or actually identical?
==(abstract equality operator) compares two values after doing the “necessary” type conversions===(strict equality operator) also requires the types to be the same
Examples:
false == 0 // as true as in Python
false == '0' // also true!
false === 0 // false
false === '0' // also false, thankfully
String replacements
In Python,
s.replace("x", "y")
replaces all occurrences of "x" in s with "y", whereas in WhateverScript it only
replaces the first occurrence of "x" in s with "y".
The modern (2021+) WhateverScript equivalent of Python’s replace is
s.replaceAll("x", "y")
if you are working with anything older, use a global regex:
s.replace(/x/g,"y");
React
Using variables
{variable}
Passing a tag its props
If a tag was a function, props would be its (named) parameters:
<Tag propName={propVal}/>
<!--or simply-->
<Tag {propVal}/>
Vue
(which did not change my views on web development)
Single File Components
This is the idea that everything you learned about the separation of concerns is wrong and that it is indeed a good idea to have everything in one file, which will end up looking something like this:
<template>
<p ref="example">Normal HTML but with , called "slots" and filled with "props" (like in React)</p>
<!-- ...and and some weird attributes.
For example, ref basically means id but isn't a synonym for id -->
</template>
<script>
// JS/TS but maybe with some additional structure, like
export default {
name: "HolyParagraph",
props: {
holeFiller: String
},
// not to mention that components are like classes enough that they can have
methods: {
onClickOrSomething() {
// why would I even click on a paragraph?
},
...
}
</script>
<style>
/* some of those cursed rules, if you really have to */
</style>
Passing a tag its props
Like React, but worse:
<HolyParagraph :holeFiller="stuff">
note that "stuff" is not a string whose content is the word “stuff”, but the name of a variable (or it could be anything, really) in quotes.
Instantiating components programmatically
Kushagra Gour said it better than me, but I will say it shorter.
If a component is like a class enough that it has methods, you would think that you can use it like an class:
var p = new HolyParagraph(stuff);
// append to another component or do whatever you want with it
…but no, it’s more like:
import Vue from 'vue'
var HolyParagraphClass = Vue.extend(HolyParagraph); // make the component a class, I guess?
var p = new HolyParagraphClass({ // instantiate it
propsData: { holeFiller: stuff } // concisely pass it the props
}));
instance.$mount() // go figure
// append to another component or do whatever you want with it
In Kushagra’s tutorial there’s another step too, but I skipped that because I was not sure what it was talking about and my code worked anyway.
Events
When children want to communicate with their parents, they $emit events:
<!-- Excerpt form a hypothetical Child.vue -->
<script>
export default {
methods: {
askDad() {
this.$emit("question", "Why is there time? Why is there space? Why are there dogs and cats and trees and the human race?");
}
}
}
</script>
Here’s how parents handle specific events:
<!-- Excerpt form a hypothetical Dad.vue -->
<template>
<Child @question="handle"/>
</template>
<script>
export default {
methods: {
handle(message) {
console.log("Go ask your mom or just go away!");
}
}
}
</script>
@event is a newer synonym for v-on:event, which in turn is similar to plain JS onEvent (so for instance onClick becomes v-on:click in Vue and now also @click).