Inline file in bundle with fs.readFileSync not working with TypeScript
alexharri opened this issue ยท comments
๐ 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)
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 |
I'm having the same problem. Has anybody found a temporary workaround?
@ishaantaylor I showed a possible workaround in the Context section of the issue, should work if allowJs is enabled in the tsconfig.
Lines 162 to 173 in c9c5805
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(#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');
Is there another issue to support transforming this readFileSync
when not using named imports?
Is weird that we can do fs.readFileSync()
in .js files but not in .ts/.tsx files.
Hello Guys,
I am facing a similar problem
I have imported "fs" using import * as fs from "fs" and trying to execute fs.readFile() and fs.readFileSync with there respective arguments.
But, getting an error as "fs" object doesn't have a function readFile() and readFileSync().
I have tried using var fsFile = require("fs");.
I am using in Cypress automation project in typescript.
I'm running into this issue trying to use the adl-xapiwrapper
library with Typescript, using import ADL from 'adl-xapiwrapper'
. The actual fs.readFileSync
call is several layers of require
statements down from adl-xapiwrapper
, in mime.js
. Here's the callstack where I get the fs.readFileSync is not a function
error. This is parcel version 1.11.0
Mime.load (mime.js:54)
parcelRequire.../node_modules/mime/mime.js.path (mime.js:90)
newRequire (src.f69400ca.js:49)
localRequire (src.f69400ca.js:55)
parcelRequire.../node_modules/request/request.js.http (request.js:16)
newRequire (src.f69400ca.js:49)
localRequire (src.f69400ca.js:55)
parcelRequire.../node_modules/request/index.js.cookie-jar (index.js:20)
newRequire (src.f69400ca.js:49)
localRequire (src.f69400ca.js:55)
parcelRequire.../node_modules/adl-xapiwrapper/lib/adl-xapiwrapper.js.request (adl-xapiwrapper.js:11)
newRequire (src.f69400ca.js:49)
localRequire (src.f69400ca.js:55)
parcelRequire.index.tsx.react (index.tsx:11)
newRequire (src.f69400ca.js:49)
(anonymous) (src.f69400ca.js:81)
(anonymous) (src.f69400ca.js:107)
Edit: not quite sure this is the same bug, I'm actually getting this just with a plain js file trying to import adl-xapiwrapper
, perhaps I'll make a separate issue for it.
I have the same problem, even with named imports it does not get inlined.
Input:
export async function setSchema(dgraphClient: DgraphClient): Promise<void> {
// This gets bundled by Parcel
const schema = readFileSync(__dirname + '/../dgraph.schema', 'utf-8')
const op = new Operation()
op.setSchema(schema)
await dgraphClient.alter(op)
}
Output:
async function setSchema(dgraphClient) {
// This gets bundled by Parcel
const schema = fs_1.readFileSync(__dirname + '/../dgraph.schema', 'utf-8');
const op = new dgraph_js_1.Operation();
op.setSchema(schema);
await dgraphClient.alter(op);
}
I have the same problem, even with named imports it does not get inlined.
Could you please share your tsconfig or a complete reproduction?
Works for me with this typescript:
import { readFileSync } from "fs";
export function setSchema() {
const schema = readFileSync(__dirname + "/test.schema", "utf-8");
console.log(schema);
}
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs.
Working with Parcel 2.4.1 and this seems like it's still happening. Would it make sense to reopen the issue?
Can someone reopen this? How does it get closed?
@bibek-stripe @spion Can you provide a reproduction? When I tried it in #1736 (comment), it worked fine
Sorry, never mind - looks like this is a different issue - its the use of template strings that doesn't work:
fs.readFileSync(`${__dirname}/path/to/file.txt`)
is simply not recognized.
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);
Hello!๐
First, I encountered the same exact issue; fs.writeFile
doesn't work within .ts
files.
Then, I update my package.json
just using:
{
"source": "src/create-projects.ts",
"main": "dist/create-projects.js",
"type": "module",
}
And voilร ! I can parcel build
and run a node dist/create-projects.js
to create my file.
I hope this can help you.