[RFC] Specify sub directory for all the generated assets for easy deploy and serve
npup opened this issue Β· 33 comments
TLDR;
My point is that serving the built project (both in prod and dev) could be so much easier in the common case if generated assets were not necessarily put alongside the main index file -- and an option for it could carry its weight.
What am I talking about?
Consider having a src/index.html
file, referring css and js files (living anywhere in the src tree).
Without any options used when bundling the resulting assets are generated alongside the index.html in ./dist/
like:
dist/
index.html
50c20e2a4174028d1e9d4574129f6104.css
50c20e2a4174028d1e9d4574129f6104.js
-- and the index.html is rewritten to refer them nicely.
SPA stylee, the dist
folder is to be statically served by nginx/equivalent, and for a seamless dev experience I'd like to deploy it as is -- or even build it in place on Heroku or such.
For that, I would love a build option to say "all the generated assets should live in a sub directory by the name of foo". (We already have an output-dir
option, which sets the name of the whole build output, and a public-url
option, though the latter just affects the referring paths in index.html (in this case) ).
This could the the result of my idea:
dist/
index.html
foo/
50c20e2a4174028d1e9d4574129f6104.css
50c20e2a4174028d1e9d4574129f6104.js
That way nginx/whatever could happily serve index.html for all requests but foo
and under.
An alternative would be
- using the
public-url
option to have index.html refer assets infoo
- having a post build step to "manually" move asset files to
dist/foo
, but this juggling does not work very well in development mode, wanting nginx to serve files in the same manner from the local dist/
.
Creating a more elaborate bunch of rules for the file server to have it avoid serving index for any generated asset file is another cumbersome route I'd happily avoid :D .
Is this essential to making SPAs? Can we avoid having to add more to our CLI by just letting NGINX handel all of this rather than parcel?
@davidnagli
Thanks for chiming in!
An SPA was my initial use case (and used in my example), though I'd like to see it as a generally nice feature just to to be able to say where my generated files shall end up.
If we are talking developer experience, this is really quite helpful (for other post processing too!). Hey, in comparison, the output-dir
option does not help as much, but it is still there ;).
As for the SPA case -- leaving the generated structure flat with no options (leaving the web server to handle this) is really not very ergonomic in the general case. Again, makes for a really smooth developer experience, which is something I sensed is a goal of this cool tool.
Ya I definetly see where youβre going with this. It seems like a pretty important feature.
How do you think we should implement this?
The whole point of Parcel is that there is no configure file, so we would want to implement it in a way thatβs very automatic. I just canβt figure out how to design it in a way that is actually easy and productive for developers.
wouldn't nginx's try_files
directive solve the problem?
location / {
try_files $uri /index.html;
}
this will make nginx to try and serve a file under the request uri and otherwise fallback to index.html
it might be worth creating a guide for such case for common web servers.
@mrbar42 that's a nice one, but nginx and/or SPA are not the only reasons to need the generated files/assets to be easily distinguished in the general case -- be it in the form of naming a directory for them or having the files prefixed or whatever.
@davidnagli What would the major problem be with a cli option like the existing public-url
and output-dir
, that makes the generated files land (and be referenced) in a directory with a certain name?
From an SPA development perspective, is it essential that we give you control over the name of that directory (/foo
in your example)? Can we just throw all the generated bundles into a subdirectory called bundles
or something?
@davidnagli That would be the next best thing I suppose (and not only for SPA use cases, sorry if that part of my argument stuck), in that it facilitates various post build operations. I really can see (and appreciate) the effort to keep the configuration explosion on a leash.
Though I foresee continuous proposals about being able to name the bundles
dir too, especially since one already can set the name of the main output dir. Let's see what happens :)
I also have the same problem:
parcel Can not be configured
html, js, css
such as multiple files, output to multiple directories/views/dist, public/assets/js/hash.js, public/assets/css/hash.css
For example, the following is the file structure of the backend rendering project based on express
βββ README.md
βββ app.js
βββ config.js
βββ middlewares
β βββ auth
β βββ csrf
β βββ jwt
β βββ util
βββ public
β βββ assets
β β βββ css
β β βββ img
β β βββ js
β βββ debugger
β βββ css
β βββ img
β βββ js
βββ ssl
βββ views
βββ dist
βββ src
βββ index.html
βββ layer.html
parcel build /views/src/index.html -d /views/dist/index.html --public-url /assets/js
?
parcel is great, packaging efficiency is very fast, but it can not configure the corresponding file path, a bit regrettable... But I'll still pay attention to it
Is this still not possible? I have a Flask app with the following structure:
ββββmain.py
ββββpackage.json
ββββjs
β ββββapp.js
β ββββutilities.js
ββββsass
β ββββbase.scss
β ββββhome.scss
β ββββvars.scss
ββββstatic
β ββββimages
β ββββscripts
β ββββstyle
ββββtemplates
ββββindex.html
By default, Flask apps serve static content (js, css, images, etc) from static/
and html files from templates/
.
I want Parcel to bundle the files from js/
and sass/
into static/scripts/
and static/style/
respectively. templates/index.html
should also be updated to reference these files.
Currently everything is put into a dist/
folder, losing all structure. Is there are workaround for this?
Ideally, to cater for all types of projects, it should be possible to specify different output directories for different entry points. In Webpack, you can specify to output css into path/a/
, js into another/path/b/
, and html into c/
(for example).
Would love to see some official word on this. I don't find much sense for a project where the index.html
is the build entry point and all the assets are just grouped together and outted to the same directory. I don't find this to be a practical, useful or even standard approach to file organization across any language or project.
This is the one issue where I find Parcel's "no config" approach to be a fatal flaw as it basically defines how all projects must be structured and does so without any logic.
Imho Parcel should recreate the existing project structure for imported files. This would allow infinite flexibility (users could just do whatever and it would work for them) and it could always be overwritten using a config file.
This would be useful for me too, maybe even a /assets/ folder or anything similar so when i have 200 + images they arnt all in the root
I've run into this limitation today.
I'm using parcel to build my express app which is server side renderering a react app.
I was about to add this line to the express app:
app.use(express.static(path.join(__dirname)));
to serve all the web-app assets but clearly this would be really bad because with the build folder being flat that means GET /index.js
would return my server side code!
@Place1 how would that happen? do you store your index.js
in the dist folder?
if your project looks like this
-/
- dist/
- *.{html,js,css,png,woff2,...}
- index.js
then you should do something like this
app.use(express.static(path.join('dist')));
which wouldn't expose your server code
I run my backend through parcel to concert jsx using βtarget=node
then you can call parcel twice with different out-dir
, once for the clinet with dist/client
and once with dist/server
and have your express static point dist/client
I was surprised to see that if I have a folder structure:
src
index.html
css/style.css
js/app.js
Everything would just be dumped out in a flat file structure in the dist
folder. It would be nice if the dist
folder followed the same structure as my src
folder. Not sure if this is what @hacknug meant.
Yes! This is exactly what I meant.
It's hard to make this the standard as you could end up having a very deeply nested tree. And in most cases it just gets dumped onto a server anyways, besides that some terminal magic and you can find any file in seconds no matter how flat and big the folder is.
Note: this will be possible once parcel 2 gets released as you'll be able to use your own naming strategy (or a premade one {the default will remain the same}), this will allow anyone to use hashes, filenames and folders however they want
I don't think we'll support recreating the entire source file structure as it could be quite deep and nested as Jasper mentioned. I could see supporting a single "assets" directory where content hashed files could go, with other entry points at the top.
That being said, in Parcel 2 you'll be able to override the naming strategy using plugins, so I assume the community will come up with some good options for different use cases which we can bring back into core as needed.
Closing this since it will be solved in Parcel 2 via plugins.
I would like to add a possible solution to create high-level asset folders:
|---/js
| |---index.js
|---/css
| |---index.css
|---/assets
| |---/fonts
| | |---font1.woff2
| | |---font2.woff2
parcel build js/index.js assets/fonts/* css/index.css
which creates:
|---/dist
| |---/js
| | |---index.js
| |---/css
| | |---index.css
| |---/assets
| | |---/fonts
| | | |---font1.woff2
| | | |---font2.woff2
My plugin makes it, based on the publicURL : https://www.npmjs.com/package/parcel-plugin-pre-dist
My plugin makes it, based on the publicURL : https://www.npmjs.com/package/parcel-plugin-pre-dist
give us more information about usage of your plugin..
When developing parcel does not use the dist folder. This means that if you copy assets to the dist folder, the server cannot see them. So when using something like parceljs etc they're not visible during development and cannot be tested.
His plugin allows you to set a pre-dist folder, which you can copy your assets to. This means that you can test assets in development.
The solution for this problem and any other asset naming and structure is can be solved by a "custom Namer plugin" in Parcel 2:
(ref: #2991, #2991 (comment))
You can write a custom Namer plugin to support things like this. See how the default namer works for an example: https://github.com/parcel-bundler/parcel/blob/v2/packages/namers/default/src/DefaultNamer.js
When will Parcel 2 be released(stable)?
This question has been bothering meοΌHope that the official solution
When developing parcel does not use the dist folder.
Has this changed since then, because when I run parcel it definitely does. Which is annoying as hell as parcel index.html
and parcel build index.html
both dumps everything in the dist folder, but since parcel renames everything I have two copies of every asset. One from my development phase and one from the build.
I really want parcel to be THE tool to use for web development, but at the moment it seem to still be in its infancy and not ready for production.
I have created a Parcel 2 namer plugin which puts assets into a directory called a/
. It is the simplest possible solution but solves my use case. It should be easy to add some configuration to support more naming schemes.
Having this issue for too long, I've decided to make a plugin that will solve this.
The simple, but very powerful plugin that supports modern web development needs.
https://github.com/VladimirMikulic/parcel-plugin-custom-dist-structure
Look how simple it is!
First, install it by running npm i parcel-plugin-custom-dist-structure -D
.
In your package.json
provide a configuration object.
"customDistStructure": {
"config": {
".css": "css",
".js": "js",
"images": [
".jpg",
".svg",
".png"
]
}
},
# Build your project
parcel build index.html
Congratulations, this your dist folder:
dist
βββ css
β βββ styles.hash.js
βββ images
β βββ img1.hash.png
β βββ img2.hash.jpg
βββ js
β βββ script.hash.js
βββ index.html
Let me all know what you think!
Is there built-in functionality in version 2 to configure output directories or do I need to install a plugin? If I need to install a plugin, which plugin? I tried VladimirMikulic's plugin but apparently, the plugin only works for Parcel version 1. The link to version 2 takes you to somewhere seemingly unrelated. I would be surprised if there isn't built-in functionality for something so basic.