-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SyntaxError: Unexpected token 'export' #28
Comments
Hi. client-zip is meant to be used in a browser (there are faster alternatives in Node.js) and is therefore released as an ES6 module only. Node.js supports the ES6 module syntax, but you have to ask nicely and you'll also be missing a few Web API globals that client-zip rely on. |
My point is, I suspect your project is configured to only understand CommonJS imports and probably also to output ES5-compatible code (a shame, really, but those big projects tend to value backwards compatibility way too much…). One way around it would be to exclude the client-zip import from bundling — import it only at runtime in the browser. |
Any luck fixing your module problem, @FullyFerret ? it's a bit off-topic, but it could still be useful to other users with a similar setup if you explained how you fixed it before closing the issue. |
@Touffy I was helping a friend debug something similar Unfortunately with nextjs the solution isn't simple. There are two things that can be done in nextjs to use this: You can use a nextjs dynamic component which is only rendered client side: const FileAttachmentLink = dynamic<Attachment>(
() => import('./file-attachment-link').then((m) => m.FileAttachmentLink),
{
ssr: false
}
) Then, in that component, you can use a dynamic import to avoid it being included on the server. For example in a callback, you could do the following: export function DownlaodFileLink() {
async function onDownload() {
// import the library dynamically at runtime
const { downloadZip } = await import('client-zip')
const code = await fetch(
'https://raw.githubusercontent.com/Touffy/client-zip/master/src/index.ts'
)
const intro = {
name: 'intro.txt',
lastModified: new Date(),
input: 'Hello. This is the client-zip library.'
}
// get the ZIP stream in a Blob
const blob = await downloadZip([intro, code]).blob()
// make and click a temporary link to download the Blob
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = 'test.zip'
link.click()
link.remove()
}
return (
<a onClick={onDownload}>
{filename}
</a>
)
} |
Right. I was afraid you'd have to do something like this. Obviously we don't want client-zip on the server-side. It won't work, and it's not like Next would understand "server-side rendering" the Zip file anyway even if it could parse the code. This method also has a little performance drawback because you import client-zip just when you need to create the Zip file (the first time, anyway), so it will add a bit of latency. That can be fixed easily by moving the |
Thanks @venkatd for the code example. @Touffy thanks for the good work on this package. I came hunting for this question. It may seem silly given the package name is literally "client-zip" but it wasn't immediately evident to me that this only works in a client environment. I was also trying to integrate with nextJS. I imagine other folks will try to do similar things given the popularity of frameworks like nextjs right now, maybe it is worth elevating the discussion of using this package with SSR to the docs somewhere? |
I'll try to find some room for it along with the CSP tips in the next minor update. |
Forgot to do it before the update… oh well, at least it's on GitHub now, will be pushed to NPM along with the next version… probably when I complete Content-Length prediction. |
|
The faster alternative in Node is to call a (fast) native Zip program. I am not an expert on those, and I'm sure there are already performance reviews you can find elsewhere. I don't mean to be rude, I just don't want to give you poor advice from a lack of research, and I don't see why I should do the research. Zipping on the server-side is off-topic for this project. It happens to work in Deno, yes, but that wasn't even intended. However, there is a general explanation I can give you. Native programs can use CPU features that are not available to client-zip (because they're not in JavaScript or WebAssembly), such as a hardware CRC32 primitive, and 256-bit vector operations. Also, Node and native programs have efficient random access to the local filesystem, which means they don't have to use streaming mode if zipping from there, and they can copy data from one part of the filesystem to another with efficient kernel calls instead of moving it through userspace buffers. As you can see on my benchmark, the native Zip program I used is much faster than client-zip and other JavaScript alternatives. However, I can't say if it's the fastest, or the best suited for integration with Node. |
@Touffy I hit the same issue while running tests with |
The problem is not React or jest, it's their configuration. You can either make them understand ESM imports, or skip the whole thing by making the import dynamic at runtime. The details will depend on your existing setup. |
I just realized that for tests I can probably mock |
That's right. You probably don't need to run |
Describe the bug
I get the following error when trying to import the package like so
import { downloadZip } from "client-zip";
:To Reproduce
Steps to reproduce the behavior:
SyntaxError: Unexpected token 'export'
Additional context
I am developing a project in NextJS and TypeScript, but everything else is working properly.
The text was updated successfully, but these errors were encountered: