Compile typescript with Hugo pipes?
Asked Answered
J

2

6

Is there a way to compile Typescript to JavaScript using the Hugo pipes? I'm currently using "hugo server" to run my site locally and would like to continue doing so for the live reload and ease of running. However I am now in a situation where I need to compile some typescript but I can't find any resources that suggest Hugo is able to do this.

Is there any way I can keep my live-reload easy while compiling Typescript for use in Hugo?

Joaniejoann answered 20/2, 2020 at 15:39 Comment(0)
C
5

Yes you can!

Hugo uses Babel to compile JavaScript and through Babel you can also compile TypeScript. If you haven't already, you'll need to install some Babel packages for Hugo to use:

@babel/core @babel/cli @babel/preset-env

You'll also need Babel's TypeScript package:

@babel/preset-typescript

Setup your Babel config file (Hugo looks for babel.config.js, but you can change that if you'd like):

module.exports = {
  "presets": [
    "@babel/preset-typescript",
    "@babel/preset-env",
  ],
}

Now Hugo can successfully compile TypeScript via Babel with the babel pipe:

{{ $typescript := resources.Get "scripts/main.ts" | babel }}

The problem is that Hugo will save this as 'scripts/index.ts' in your public directory. So, to fix this, you have to change the file during the process. One way is to take advantage of Hugo's asset bundling and essentially bundle itself as a new file:

{{ $javascript := slice $typescript | resources.Concat "scripts/main.js" }}

Finally, you can use that resource:

<script src='{{ $javascript.RelPermalink }}'></script>

<!-- or -->

<script>{{ $javascript.Content | safeJS }}</script>

Edit

There is one caveat: since Babel is not bundler and Hugo's bundler doesn't seem to support JavaScript modules, you can't import modules and have the same expected outcome as a bundler like Webpack.

It does look like, however, that this is currently a proposal for Hugo https://github.com/gohugoio/hugo/issues/7290.

Claver answered 13/7, 2020 at 18:3 Comment(0)
L
11

Yep. You can do it with Babel like dmbdesignpdx explained above.

However, if you are using Hugo v0.74.0 or later you can use TypeScript much more easily with ESBuild (See Github release info). Plus you can use import statements.

Let's say you have the following folder structure in your assets folder:

├── assets/
    └── ts/
      └── app/
         ├── main.ts
         └── MyClass.ts

Where you have:

// MyClass.ts
export class MyClass {

  sayHello(s: string) {
    return `Hello ${s}`;
  }

}

In main.ts you can have an import statement:

// main.ts
import { MyClass } from "./MyClass";

let testInstance = new MyClass();
console.log(testInstance.sayHello("World"));

Then you can use the resource in your layouts like so:

{{ $js := resources.Get "ts/app/main.ts" | js.Build }}
<script src="{{ $js.Permalink }}" defer></script>

When you run hugo server in your terminal, the TypeScript files will automatically be combined and will yield a single JavaScript file called main.js

Localism answered 5/7, 2021 at 5:19 Comment(0)
C
5

Yes you can!

Hugo uses Babel to compile JavaScript and through Babel you can also compile TypeScript. If you haven't already, you'll need to install some Babel packages for Hugo to use:

@babel/core @babel/cli @babel/preset-env

You'll also need Babel's TypeScript package:

@babel/preset-typescript

Setup your Babel config file (Hugo looks for babel.config.js, but you can change that if you'd like):

module.exports = {
  "presets": [
    "@babel/preset-typescript",
    "@babel/preset-env",
  ],
}

Now Hugo can successfully compile TypeScript via Babel with the babel pipe:

{{ $typescript := resources.Get "scripts/main.ts" | babel }}

The problem is that Hugo will save this as 'scripts/index.ts' in your public directory. So, to fix this, you have to change the file during the process. One way is to take advantage of Hugo's asset bundling and essentially bundle itself as a new file:

{{ $javascript := slice $typescript | resources.Concat "scripts/main.js" }}

Finally, you can use that resource:

<script src='{{ $javascript.RelPermalink }}'></script>

<!-- or -->

<script>{{ $javascript.Content | safeJS }}</script>

Edit

There is one caveat: since Babel is not bundler and Hugo's bundler doesn't seem to support JavaScript modules, you can't import modules and have the same expected outcome as a bundler like Webpack.

It does look like, however, that this is currently a proposal for Hugo https://github.com/gohugoio/hugo/issues/7290.

Claver answered 13/7, 2020 at 18:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.