Call me old school but I still use gulp, because it’s easy to comprehend over the monster webpack is. I can write
a gulpfile.js
from scratch and modify it using streams but I wouldn’t remember how to start a webpack project
without create-app-starter
.
Also, I lied, you can’t do this without module loaders, but you can almost do it without them. Confused? So was I,
the idea is to use the module loader to do the minimum amount of work and not disrupt your workflow by a lot!
My current predicament has been my own doing, and this is probably the universe sending me a signal
My project consisted of a single js/booking.js
file which I wanted to port over to typescript which I love.
I was foolish to think that this would take me an hour or two, I was not ready for the Pandora’s box that I was about to
open.
Prima Facie, my assumption was that npm i -D typescript gulp-typescript
and a simple recipe to transform should do the
job. It wasn’t that simple and boiled down to multiple reasons:
- You cannot use typescript without a module loader. Battered and bruised, I finally resorted to using
SystemJS
becauseamd
does not supporttop-level await
. You have to add module: “system” intsconfig
for this to work. - You need to use the
outFile
option intsconfig.json
for it to generate a standalone file. - Only
SystemJS
does not cut it and you need to import/extras/named-register.min.js
becausegulp-typescript
creates a named module. - You have to import the created module in your
index.html
usingSystem.import('booking.js')
. - Do not use
import Vue from 'vue'
syntax, instead useimport type Vue from 'vue'
. This will save you a whole lot of pain in trying to resolve dependencies in your files. After this, you can use a bare script tag to import Vue as a global in the browser.
I’m listing down the main components of all the files for your reference.
gulpfile.js
const ts = require('gulp-typescript');
const tsconfig = require('./tsconfig.json');
function js() {
return gulp
.src(['ts/booking.ts'])
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failAfterError())
.pipe(ts({
...tsconfig.compilerOptions,
outFile: 'booking.js',
}))
.pipe(gulp.dest('./dist/js'))
.pipe(browsersync.stream());
}
tsconfig.json
{
"compilerOptions": {
"moduleResolution": "node",
"target": "es2017",
"sourceMap": true,
"module": "system",
"removeComments": true,
"esModuleInterop": true,
"strict": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"forceConsistentCasingInFileNames": true,
"typeRoots": [
"ts/declaration.d.ts",
"node_modules/@types"
]
},
}
index.html
<script src="path-to-vue"></script>
<script src="path-to-systemjs"></script>
<script src="path-to-systemjs-named-register"></script>
<script src="path-to-generated-booking.js"></script>
<script>
System.import('booking');
</script>
Hope this helps saves a few hours of desperate wuts.