TLDR
Go to the repo
clone
: Template repo
cd
into the clone
d directory
npm i
npm start
to fire up Parcel localhost
server.
Write your code π©πΎβπ» π¦
What's It All About?
Summarily, if you are a newer dev, it can be distracting to set up tooling and linting and other 'dev tools π§°' to have a reductive workflow.
This template is for writing a Vanilla SPA application (good to do as a prerequisite to React, Vue, etc.) using "parcel-bundler"
.
So, you can dive right in and have a set of 'battle-tested' tooling helping you learn and develop and be more reductive overall. π€
As you progress, you adjust the each and everything as you see fit. It grows/adapts with you. π
It's helped hundreds of my previous π¨πΎβπ in bootcamps ποΈ and college π« courses.
VS Code Extensions & Settings
When you π₯ this up in VS Code, you will be prompted in the bottom right to install some extensions. These are listed in the '.vscode' directory π.
To take full advantage dl and install πͺ.
Linting/Prettier for CSS & JS
It's using extends: ["airbnb-base", "prettier"]
. β οΈ "airbnb"
linting is very strict! π I strongly encourage you to stick with it and research the linting 'mistakes' b4 just turning them off.
I've already adjusted a few for you:
rules: {
"array-callback-return": "warn",
"import/extensions": "warn",
"import/prefer-default-export": "warn",
"no-plusplus": ["error", { allowForLoopAfterthoughts: true }],
"no-unused-expressions": ["error", { allowShortCircuit: true }],
"no-unused-vars": "warn",
},
Prettier
There is some very basic "prettier"
config stuff in other files, but we just use the default stuff for that one.
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": "eslint --cache --fix",
"*.css": "stylelint --fix",
"*.{js,css,md}": "prettier --write"
}
We have also activated 'pre-commit πͺs.' This prevents commit
ting of code that doesn't pass the linter. It also 'auto-formats' the code for consistent repo code.
CSS
Stylelint also is riding along. CSS mistakes can be easy to make, and it can get sloppy. This will guide along the way and prevent some common CSS specificity issues.
Project Entry-Point π
The entry point is: 'index.html'. Γ la React, we have a root
that will wrap our functional components, which will come from 'index.js.'
<!-- TODO: 'render' content here -->
<div id="root"></div>
<script src="./index.js"></script>
And, in 'index.js,'
/**
* TODO: Import some components
* U might also need to import 'api' to get your initial data?
*/
import testComponent from "./components";
const root = document.getElementById("root");
const render = () => {
root.innerHTML = testComponent();
};
// β οΈ Don't 4get to actually render! π
render();
// TODO: Use api to 'fetch' 'initial data?' Maybe 'api.index()'?
Modularity
Each of the other 'module' directories contain 'index.js' files and you can build in other files as needed from there. I've already included some comments and/or starter code in each one. We take a look at each briefly.
'api/index.js'
/**
* TODO: All interactions with external data should be managed from here.
* You probably need to 'import' stuff from 'db' if using a database.
* Then you can create methods such as 'index,' 'create(payload),' etc.
*/
As an example, this might turn into something like shown below. Specifically, this would apply very closely if you were using Firebase's Firestore for data management - that's not really important for what we are doing here.
The point is to maintain a separation of concerns/services. It's going to 'api's job to manage interacting with external sources.
import db from "./db";
export default {
async index() {
const querySnapshot = await db.collection("students").get();
return querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
},
// More generically, the PARAMETER might be called 'payload'
async create(student) {
db.collection("students").add(student);
},
// TODO: Add addl. 'api methods' ππΎ if needed
};
'db'
This π s your connection to an external database service. It is subsequently used by 'api' - in fact, this directory could be π ed inside of 'api'...and in fact I am going to change that!
Anyway, 'db/config.js' is for any configuration details that you might need to connect to your database. If these are supposed to be 'secret,' you should look into using a '.env,' or, even better, keep that on server-side.
'db/client.js' is for establishing and export whatever database clients are created using your configuration details.
Finally, as always...as always...'db/index.js' is there to simply export
out whatever 'api' might need to use.
'components'
This is what initially renders, and is where most of your work will probably be done. As your app grows, you may even need a 'pages' directory π and a 'layouts' directory π¦.
In this one, we see a simple example of a functional component: export { default as Main } from "./Main";
. It's nothing but a function that returns some HTML markup, in this case.
Again, this is really where you may end up with a lot of work π¦ depending on your app's needs. This directory could end up looking π something like:
'lib'
This is where we might keep various 'utility functions' that our components might need to import
to do their respective jobs.
'store'
This is to enforce a 'single source of truth' concerning the state of our data at any given time in our app. It's a 'data store' or 'data library.' I don't really like the name 'store,' but that's what the dev community says it is. As Petey Pablo says, "Who am I?"
There are many strategies for doing this, but I've included the following starter π± code to do with as you see fit:
export default {
data: [],
setData(newData) {
// 'concat' is 'non-mutating'
this.data = this.data.concat(newData);
},
};
Summarily, any part of your app that either wants to 'get' or 'set' data should do this via the 'store' - a single source of truth. This is the foundation upon which Redux/Vuex/Flux, etc. are based on.
There's a Lot! π¦
Well, I hope this helps more than it hurts. There's a lot to consider...but just get started with this and grow into it. You don't have to use each part of this! Really, just rendering a few functional components is fine.
If you do want to see a somewhat simple example of making something with this, here's a project repo of something we worked on in one of my college class.
Reach out if you need a bit more guidance. I have other template repos too for other stuff.
Update: For a more in-depth discussion, join my GitHub discussion.
Top comments (0)