parcel: Inline file in bundle with fs.readFileSync not working with TypeScript

๐Ÿ› bug report

Parcel provides inline asset importing via statically analyzable fs.readFileSync statements. They work as expected in JavaScript but not Typescript.

๐ŸŽ› Configuration (.babelrc, package.json, cli command)

package.json

{
  "scripts": {
    "start": "parcel index.html"
  },
  "dependencies": {
    "parcel": "^1.9.6"
  },
  "devDependencies": {
    "@types/node": "^10.5.2",
    "typescript": "^2.9.2"
  }
}

No custom .babelrc file

๐Ÿค” Expected Behavior

A statically analyzable fs.readFileSync statement should inline the file in the bundle, both in .js and .ts files.

๐Ÿ˜ฏ Current Behavior

fs.readFileSync statements are inlined in .js files but arenโ€™t in .ts files.

Output from console (see code sample)

Console output

index.ts:5 Uncaught TypeError: fs_1.default.readFileSync is not a function
    at Object.parcelRequire.index.ts.fs (index.ts:5)
    at newRequire (2.0d1d60a5.js:48)
    at parcelRequire...\node_modules\parcel\src\builtins\_empty.js (2.0d1d60a5.js:80)
    at 2.0d1d60a5.js:106
parcelRequire.index.ts.fs @ index.ts:5
newRequire @ 2.0d1d60a5.js:48
parcelRequire...\node_modules\parcel\src\builtins\_empty.js @ 2.0d1d60a5.js:80
(anonymous) @ 2.0d1d60a5.js:106

๐Ÿ’ Possible Solution

Implement inline file imports in .ts files.

๐Ÿ”ฆ Context

I was working with WebGL and writing shaders. Writing them with template strings didnโ€™t give me any syntax highlighting so I wanted to write them as .frag and .vert files. I expected to be able to import them easily with Parcel but received the above error. After a bit of head-scratching I realized it was a Parcel + TypeScript problem and made a repro.

Thereโ€™s a fairly simple workaround this issue, which is just creating a .js file which imports the desired file, for example.

// index.ts

import textFile from "./textFile.js";

// Do stuff with the text file.
// textFile.js

import fs from "fs";

const textFile = fs.readFileSync(__dirname + "/textFile.txt", "utf8");

export default textFile;

It works but could create a lot of noise if using a lot of inline assets.

๐Ÿ’ป Code Sample

Repo with code to reproduce the issue.

๐ŸŒ Your Environment

Software Version(s)
Parcel 1.9.6
Node 8.9.1
npm/Yarn npm 6.1.0
Operating System Windows 7

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 15
  • Comments: 15 (3 by maintainers)

Commits related to this issue

Most upvoted comments

@ishaantaylor I showed a possible workaround in the Context section of the issue, should work if allowJs is enabled in the tsconfig.

https://github.com/parcel-bundler/parcel/blob/c9c5805866aa23d2a4e1809516d04c4296c0c17c/src/assets/JSAsset.js#L162-L173 There is a regex in JSAsset that launches FSVisitor. So my intuition (Iโ€™m researching it for like 5 minutes, so I might be wrong) is we should add transform method override to TSAsset and launch FSVisitor from there.

Disregard whatโ€™s above. Iโ€™ve added test(https://github.com/parcel-bundler/parcel/pull/2046) to my fork of parcel, got really surprised that it works and made a reproduction repo.

Named import works fine for me and all of the imports work on CodeSandbox ๐Ÿ˜ฎ .

import { readFileSync } from 'fs';
const raw = readFileSync(__dirname + '/raw.tsx', 'utf-8');

In Parcel 2, the currently recommend way to read a file as literal, plain text is using the bundle-text: scheme, as in:

import text from 'bundle-text:./myFile';
console.log(text);