Skip to content
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

Parcel 2: Serving static data from the dev server #3407

Open
magcius opened this issue Aug 15, 2019 · 26 comments
Open

Parcel 2: Serving static data from the dev server #3407

magcius opened this issue Aug 15, 2019 · 26 comments

Comments

@magcius
Copy link

magcius commented Aug 15, 2019

🙋 Feature request

Currently, there's no way easy way to add additional data into the dist dir provided by serve. I've previously advocated for this use case (#2461), where I have large binary files like 3D data that I do not want to push through the build process. The intermediate workaround has been to place a folder symlink into the dist/ directory, which works OK -- I can filter out text/html responses on the client and pretend they are 404s.

Parcel 2 moves the dist dir into .parcel-cache, and seems to more aggressively wipe it. This means it's very hard to get Parcel 2's dev server to serve static data again. The code for serving static data is still there, however.

🤔 Expected Behavior

I would like a supported mechanism to serve static, unbuilt data from the Parcel dev server.

😯 Current Behavior

There is no way to serve static data, and the existing workarounds for Parcel 1 which were relied on by many is now effectively unusable.

💁 Possible Solution

Support extra configuration to the parcel dev server, either based on the code in #2461 or not.

🔦 Context

I believe I have provided a sufficient amount of context above.

@DeMoorJasper
Copy link
Member

DeMoorJasper commented Aug 15, 2019

We actually have something like this in parcel atm although it's kinda weird for this use-case.
We have the entire codebase hosted through the server to make sourcemaps work in dev without needing to inline code, you can see it here: https://github.com/parcel-bundler/parcel/blob/v2/packages/reporters/dev-server/src/Server.js#L75 which is mounted under /__parcel_source_root

In theory we could add a folder like /static or something. But this might conflict with existing codebases. Adding additional config for this seems like a bad idea.

Another way to fix this is using our upcoming proxy config we're working on, see: #3281 for details

@magcius
Copy link
Author

magcius commented Aug 16, 2019

I don't see why additional config is a bad idea. Parcel theoretically has similar cases with --public-dir (though this apparently was removed from Parcel 2 for currently unknown reasons).

As you might be able to guess from the votes on #1080, this is a pretty well-requested feature that is important for a lot of use cases.

@DeMoorJasper
Copy link
Member

@magcius it will be possible with proxies like I mentioned.

—public-dir never was a cli flag, I think, —public-url was removed and —out-dir got moved to config in pkg.json

Sent with GitHawk

@devongovett
Copy link
Member

publicUrl is also in package.json now, under targets.

I think ideally those files wouldn't just be copied or served by the dev server. They need to be part of the parcel asset graph as well. This will ensure they are watched, that things like HMR work, etc.

@magcius
Copy link
Author

magcius commented Aug 16, 2019

Admittedly my use case is probably a bit out there, but my static data is over 1GB+ in size, and since I fetch it with XHR, there's no way URLs could be mangled. Think of anything big like videos. Having Parcel copy 1GB+ of data would be unfortunate to me. If we could watch the static data dir in its entirety and simply trigger HMR in that case, but otherwise serve it without copying, that would be fine.

@ghost
Copy link

ghost commented Aug 28, 2019

Hello,
So far I've been using parcel-plugin-static-files-copy to solve this, but ideally this should be built-in.
Adding a +1 for this!

@mischnic
Copy link
Member

mischnic commented Nov 21, 2019

Maybe this is helpful in your case:

{
  "extends": "@parcel/config-default",
  "transforms": {
    "url:*": ["@parcel/transformer-raw"]
  }
}

you can import files which will then be copied to the dist folder:

import file from "url:./static.json"
fetch(file)...

@magcius
Copy link
Author

magcius commented Nov 21, 2019

That requires that all data is statically importable, no? If I have ./scene.json that then says "please fetch my3dmodel.bin", then Parcel can't know to that file over.

@mischnic
Copy link
Member

mischnic commented Nov 21, 2019

Correct (we just can't analyze the JSON file and guess which files you want to have available).

@magcius
Copy link
Author

magcius commented Nov 21, 2019

Right, that doesn't work for my workflow, though it might work for some others. I am suggesting a data directory that can be monitored / served directly.

@ghost
Copy link

ghost commented Nov 27, 2019

Hey, just also wanted to mention that these assets are:

  • very large
  • usually loaded anytime after build and depend on a user's choice

So it definitely needs a directory that the app has access to when it's running.

@czyzby
Copy link

czyzby commented Jan 19, 2020

This plugin was sufficient for my use case.

@odbol
Copy link

odbol commented Aug 22, 2020

Any word on progress on this? It's baffling that you spent all this time to make Parcel and Parcel 2 but it can't do the most basic of tasks which is serve up unaltered static files.

@mischnic
Copy link
Member

I think you should be able to use some static middleware with the proxy functionality: https://v2.parceljs.org/features/api-proxy/#.proxyrc.js

@subuta
Copy link

subuta commented Sep 3, 2020

Based on @mischnic 's advice, Now I can serve static files of ./static dir by following.

Create .proxyrc.js with these contents.

const serveStatic = require('serve-static')

module.exports = function (app) {
  // Use static middleware
  app.use(serveStatic('static'))
}

Then you may access your static file like this http://localhost:1234/test.txt

@jgentes
Copy link

jgentes commented Mar 8, 2021

Following @subuta's lead, I went with the approach I had used in my webpack-dev-server config (but pasted into .proxyrc.js):

const express = require('express')
const path = require('path')

module.exports = function (app) {
  app.use('/assets', express.static(path.join(__dirname, 'src/assets')))
}

@jvidalv
Copy link

jvidalv commented Apr 11, 2021

Hi, I had the same issue, but for me the .proxyrc.js was not what I needed as the files where needed in production environment too.

So I made this simple plugin that takes care of copying multiple folders and files into the specified folders once the build finishes successfully:

parcel-reporter-multiple-static-file-copier

@jw-12138
Copy link

hey there @magcius, just ran into the same issue here, still don't understand why parcel doesn't have this feature built-in.
so I wrote a script to copy static files whenever there is a file or folder has changed.

check this out:
https://gist.github.com/jw-12138/11bd9da7c3f058fce9450137b43c5fab

lipinskipawel added a commit to lipinskipawel/saifu that referenced this issue Oct 9, 2023
I have to use json-server to serve static files since parcel.js
does not support it (parcel-bundler/parcel#3407).
@Download
Copy link

Download commented Feb 6, 2024

Seems to me having a public folder with static files in them is standard. As in, literally every Node JS / Express project I ever worked on had that.

Amazing that it needs so much discussion.... The folder doesn't have to be watched or anything. There is no expectation that changing static assets under /public would trigger a rebuild. It doesn't under any other build system I ever used so why would it here?

All we need is for a folder (commonly named 'public') to be exposed under the root so that 'http://localhost:1234/my/file.txt` maps to <project>/public/my/file.txt.

I think you could include this as standard. Because the convention to have a public folder is so widely used that when people see a public folder in a project, they already know what it will do. My 2 cents.

@SeanBannister
Copy link

I'm a new Parcel user who got lured in by "The zero configuration build tool for the web." I've spent about 3 hours on this so its certainly a problem for new users. Everything else seems great though. Would of loved a /public directory like I expected.

@MarianoFacundoArch
Copy link

+1...

@ezekiel747
Copy link

it's a bit hard to believe that Parcel lacks such a simple config option to have a sort of "public" folder that:

  1. should be served accordingly as static files during dev time
  2. should be taken into consideration at build time.

I do understand the concerns of messing with existing codebases, but this shouldn't really be a problem if:

  • this option would not be enabled by default, but rather something that should be added by devs explicitly.
  • folder name would be configurable ("public", "assets", "static" or whatever the developer prefers). Or, better yet, an array of folders for devs who need more than one folder.

I'm back to this thread after more than a year, looking for the same thing. I was hoping that something changed during this time. I went with the "serve-static" plugin but that is only useful during dev time. For build you need to do your own copying if you need those files.

@devongovett
Copy link
Member

You should make the dependency on assets explicit in your code, e.g. using new URL: https://parceljs.org/languages/javascript/#url-dependencies. That will ensure your assets are copied into the dist directory when you build for production as well, the urls get content hashed, etc.

@magcius
Copy link
Author

magcius commented Jul 9, 2024

As I said nearly five years ago:

That requires that all data is statically importable, no? If I have ./scene.json that then says "please fetch my3dmodel.bin", then Parcel can't know to that file over.

@tjlusco
Copy link

tjlusco commented Oct 2, 2024

Parcel is fantastic, but the inability to serve static files without forcing them through the build pipeline is a blocker for many modern web apps dealing with large assets like videos or datasets. A solution for a simple static folder would greatly enhance the development experience and align with Parcel's 'zero configuration' philosophy.

For comparison, Vite achieves this easily with a public directory for static assets, as seen here: https://vitejs.dev/guide/assets#the-public-directory.

@devongovett
Copy link
Member

It's definitely already possible. I think this comment from 4 years ago is basically the solution I'd recommend: #3407 (comment) I think we should just document this (parcel-bundler/website#655).

This approach gives you full control of how files are served, e.g. under what URL prefix, what directory or directories to serve, what caching and other headers to apply, where to copy to the dist dir for production builds, etc. We could add a "public" folder convention, but then we'd have to make all of that stuff configurable anyway. This could get complicated very quickly, e.g. supporting multiple different sources to serve/copy files from, different renaming patterns, etc. It seems much simpler to just use existing tools like express middleware and the cp command for this instead of reinventing the wheel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests