I’ve been feeling kind of old school lately. I’ve been pining for just writing client-side code and watching it work. That’s not the world that we’re in these days.
Writing web apps has become complicated. Transpilation has made some thing really awesome, but it also has complicated the field. Webpack, Browserify, Babel and even TypeScript have all make our lives easier and awful at the same time.
I loved this tweet about our current situation:
i remember the days when people still programmed in low-level languages such as untranspiled javascript
— yan (@bcrypt) June 4, 2017
So I decided to try and use Vue without having to setup Webpack or Browserify. I know that’s sacrilege but as a thought experiment I like how it turned out.
So the plan was this:
Again, this was a though experiment as I feel like setting up webpack or browserify
First, I created a directory under wwwroot with all my TypeScript:
The idea was that each of these files would get compiled as I saved a file using the .tsconfig file to specify that:
{
"compilerOptions": {
"target": "es5",
"outFile": "wwwroot/lib/site/app.js",
"sourceMap": true,
"declaration": true,
"mapRoot": "/lib/site/",
"removeComments": true,
"module": "none"
},
"include": [ "wwwroot/app/**/*.ts"],
"compileOnSave": true
}
A couple of interesting settings here that if you’re used to using a packager might surprise you:
So what does my TypeScript look like?
/// <reference path="common/validators.ts" />
/// <reference path="common/filters.ts" />
/// <reference path="common/datepicker.ts" />
module CodeCamp {
// External JS Libraries
declare var Vue: any;
declare var VeeValidate: any;
declare var VueResource: any;
export let App = {
setup: function() {
Vue.use(VeeValidate);
Vue.use(VueResource);
CodeCamp.Common.createValidators();
CodeCamp.Common.createFilters();
CodeCamp.Common.createDatePicker();
Vue.config.errorHandler = function (err, vm, info) {
console.log(err);
}
},
bootstrap: function (theView: any) {
this.setup();
new Vue(theView);
},
}
}
Let’s walk through this to understand what I’m doing.
My goal here was to have one set of TypeScript that would be loaded on any page that needed Vue. Each page would bootstrap itself to load that part of the Vue code it needed. For that I created a partial view in ASP.NET MVC:
@section Scripts {
@Html.Partial("_VueScripts", "join")
}
This partial view took the string of which view to load and did this:
@model string
<environment names="Development">
<script src="~/lib/jquery-ui/jquery-ui.js"></script>
<script src="~/lib/lodash/dist/lodash.js"></script>
<script src="~/lib/moment/moment.js"></script>
<script src="~/lib/vue/dist/vue.js"></script>
<script src="~/lib/vee-validate/dist/vee-validate.js"></script>
<script src="~/lib/vue-resource/dist/vue-resource.js"></script>
<script src="~/lib/vue-router/dist/vue-router.js"></script>
<script src="~/lib/site/app.js"></script>
</environment>
<environment names="Staging,Production">
<script src="~/lib/jquery-ui/jquery-ui.min.js"></script>
<script src="~/lib/lodash/dist/lodash.min.js"></script>
<script src="~/lib/moment/min/moment.min.js"></script>
<script src="~/lib/vue/dist/vue.min.js"></script>
<script src="~/lib/vee-validate/dist/vee-validate.min.js"></script>
<script src="~/lib/vue-resource/dist/vue-resource.min.js"></script>
<script src="~/lib/vue-router/dist/vue-router.min.js"></script>
<script src="~/lib/site/app.min.js"></script>
</environment>
<script>
(function bootstrapVueModel() {
CodeCamp.@(Model)();
})();
</script>
So I’m loading different versions in development and production, but that little script at the bottom does the magic. It calls a bootstraper function that each vue implements (inside the CodeCamp namespace). For example:
///<reference path="./joinView.ts" />
module CodeCamp {
export function join() {
CodeCamp.App.bootstrap(CodeCamp.JoinView);
}
}
The project I did this for is an open source ASP.NET Core project that we use to run the Atlanta Code Camp. Feel free to grab the source and dig in:
I am not sure that this exercise was anything more than me pining for a time before the setup for getting started with a library didn’t require a CLI to scaffold a whole project. I’m not super happy with how this works (as I wish that the typelib stuff in TypeScript were easier to setup, but this might be a Vue problem; and I wish that there were an easy loader that would load scripts as they need them instead of the one giant file approach so I could use require and import better). But this is closer how I want to be working. I am just not sure how to get there.
At the end of the day I suspect I’ll end up with webpack and just live with the 100 lines of setup for webpack that every project needs. I just hate the way I spend more time setting a project up than actually writing code.
Feel free to flame me, but please avoid the lazy “webpack is awesome, you’re not doing it right” posts.