Skip to content

slune-org/ts-transform-asset

Repository files navigation

npm package License Build Status Coverage Status Issues

ts-transform-asset - Typescript transformer for asset imports

This transformer will simply convert imports or reexports like:

import foo from './images/foo.gif'
import * as bar from '../images/bar.png'
export { default } from './foobar.svg'
export { default as foobar } from './foobar.ico'

to:

const foo = 'assets/foo.gif'
const bar = 'assets/bar.png'
const foobar_svg_1 = 'assets/foobar.svg'
export default foobar_svg_1
export const foobar = 'assets/foobar.ico'

Language/langue

Documents, messages, code (including variable names and comments), are in English.

Anyway, because Slune is French firm, all documents and important messages must also be provided in French. Other translations are welcome.

🇫🇷 Une version française de ce document se trouve ici.

Installation

Installation is done using npm install command:

$ npm install --save-dev ts-transform-asset

Why would I need that?

You have a project using Webpack with the file-loader plugin. When this plugin finds an import foo from "./images/foo.gif", it copies foo.gif to an assets directory and change the usage of foo using the public path to the file. Great.

Then, you have another project, which contains the web server. This server, which depends on the previous project, will take the bundle and all assets to serve them to the clients. But you also want to do some server side rendering (SSR). And for this, you cannot use the bundle created by Webpack because it does not have an appropriate entry point for the server (e.g. you need to use a StaticRouter instead of a BrowserRouter). Or maybe you prefer using the transpiled javascript and definition files instead of the minified and untyped bundle.

Unfortunately, this is not working, because your server do not know what to do with your assets files.

Using this transformer to transpile the web pages (not for Webpack!), you will convert your imports into constants with the URL of where resources should be found, and dependents project will be able to work without any more configuration.

Usage

The transformer accepts the following parameters:

  • assetsMatch: a regular expression used to select asset imports, e.g., for all .png files, assetsMatch = "\\.png$". This parameter is mandatory.
  • targetName: a template similar to Webpack file-loader name used to convert the name of the asset. If you defined a publicPath in the output parameter of Webpack, then you will probably need to specify this path here too. This parameter is optional and defaults to [hash].[ext].

There is currently no way of declaring a transformer in the vanilla TypeScript compiler. If you do not want to write your own compiler using the typescript API, you can use the ttypescript wrapper.

Code

Your TypeScript code should already be well written if you are using Webpack and the file-loader. If not, you can follow the instructions below.

Module declaration

Before using them, you need to declare the new module types, for example in an assets.d.ts file like this:

declare module '*.png' {
  const content: string
  export default content
}

Older versions of file-loader (before 5.0.2) where not using a default export. You should then declare module types this way in this case:

declare module '*.png' {
  const content: string
  export = content
}

Asset import

When the (module) file is to be used:

import image from './image.png'

const url: string = image

It is even possible to re-export the asset file:

export { default as image } from './image.png'

Then, in another file:

import { image } from '../images'

const url: string = image

For older versions of file-loader (before 5.0.2), only namespace import is possible:

import * as image from './image.png'

const url: string = image

Configuration with ttypescript

For ttypescript, configure your tsconfig.json. Example:

{
  "compilerOptions": {
    "plugins": [
      {
        "transform": "ts-transform-asset",
        "assetsMatch": "\\.png$",
        "targetName": "assets/[name]-[hash].[ext]"
      }
    ]
  }
}

Notices

  • The transformer will not detect nor modify any require statement. It is advised to run it in the before phase of the compilation, before the code is converted to an older version of ECMAScript.
  • The transformer either modify the code if it conforms to what is expected, or do not touch it at all. There is an exception anyway for the re-export declarations: if the source module matches the given parameters, but the exported property is not default, then this export property will be removed.

Migration

Prior to version 3.x.x

Prior to version 3.x.x, there was a configuration entry targetPath which was the prefix used to add to the target asset name. Everything is now defined in the new targetName entry. Converting from previous to current configuration is as simple as the below example:

       "transform": "ts-transform-asset",
       "assetsMatch": "\\.png$",
-      "targetPath": "assets"
+      "targetName": "assets/[name].[ext]"
     }
   ]

Prior to version 2.x.x

In addition to the previous modifications, note that prior to version 2.x.x, transformer was of type config. Since version 2.0.0, transformer is of type program, which is the default. If you are upgrading from an older version and using ttypescript, you have to update the plugin configuration in tsconfig.json:

     {
       "transform": "ts-transform-asset",
-      "type": "config",
       "assetsMatch": "\\.png$",
       "targetName": "assets/[name].[ext]"

Contributing

Even though we cannot guarantee a response time, please feel free to file an issue if you have any question or problem using the package.

Pull Requests are welcome. You can, of course, submit corrections or improvements for code, but do not hesitate to also improve documentation, even for small spell or grammar errors.