Thanks to the work of people like @enricosada and @7sharp9, F# projects are quickly moving to dotnetcore and Fable could join the trend before 1.0.0 release. This may also be a good chance to decide if we want a specific project file for Fable or even if we just want to add the list of F# files directly to fableconfig.json. I'd like to listen to the opinion of other people but some of the ideas I've been having recently are:
files field to fableconfig.json and include the F# files there. It would still be possible to keep projFile as a fallback, but to ease maintenance and mainly to avoid user confusion I'd prefer to remove it.srcDir field (where F# files are to be found), which has been requested by some users.Fable.Core.dll by default.FSharp.Core and System libraries that only include methods supported by Fable, so FSAC would warn against any non-supported method already at design-time. The only problem is that developing Fable projects with other IDEs, while still possible, will become _foreign_.Please tell me what you think and if you have another idea, just shoot it out!
Ping @Krzysztof-Cieslak, @tpetricek, @mastoj, @fdcastel, @davidtme
I see Fable as an alternative to F# compiler (fsc.exe). One which outputs JS code instead of IL bytecode. I don't see it just as a "fancy way to generate JavaScript". For me, it's important the source compiles _both_ to IL and JS.
I've been using Fable to port existing F# libraries to JavaScript . So, my .fsproj files are already set and it would be nice to keep the projFile option to avoid to maintain two lists (one in .fsproj and another in fableconfig).
That said, I would like to stretch this discussion a little... :sweat_smile: (Food for thoughts!)
We already have a perfectly good file for including source files and to set project options: .fsproj!! So... why do we need _another_ project file"? Shouldn't .fsproj suffice?
I know... it is not the most loved format. But what can we learn from .NET Core and their attempts with project.json? Why they gave up creating their own project file and went back to msbuild-like projects (.csproj / .fsproj)? Would Fable gain any benefit adopting the existing project files instead of keeping its own?
I surely can see the benefits of keeping our own project file. Simplicity and ease-of-use -- specially for new users -- being the most obvious ones. I'm just playing devil's advocate here.
Also, the cost of adopting msbuild-like projects includes the tooling support (nobody wants a new user editing a .fsproj manually).
For the ping list, I would love to hear @dsyme opinions about this subject :wink:
We already have a fable.config but I think adopting a single file for that and the project would be a really good step, I mean everyone hates msbuild and there's no real reason to keep it for fable especially as it needs its own config anyway. The F# compiler itself has no real need for the fsproj as it has its own way to read dependencies etc anyway.
Support in ionide should be fairly easy too as its just an extension of the project.json support thats already completed.
I鈥檓 currently using Visual Studio 2015 with my fable project so using .fsproj just works for me. Wouldn鈥檛 switching to a fable.json file for the project just be helping people outside of the Visual Studio environment at the cost of us VS users?
Also I鈥檓 using symbols which mean my code adapts depending if fable or msbuild builds it. Everything I need is in one place that my tooling controls. We have the Forge for .fsproj in VSCode so why change?
Because a common request coming in is to have a sane build/project format, fsproj is not that.
Look at other ecosystems where things just work like cargo in Rust and Hex in Elixir.
uh oh!
As I wrote on twitter yesterday: If I ever have to learn a new build system/package manager I am gonna rage quit programming forever.
I personally don't like the .NET build system at all. The reason being that its mostly alien to me as I have been working with js/node mostly for the last 5 years.
But honestly that is a bad reason to be against either one of it or request a new one.
I guess we would have to decide to either stay close to the .NET eco system and its build systems (msbuild, FAKE) or to use one of the many JavaScript ones (Gulp, Grunt, lalala...).
The decision imo should be made on where we expect the most developers to come from.Are we expecting more .NET/existing F# devs moving to the Node/Browser environment or JavaScript people coming to F#? (Has anybody a good source for crystal balls?)
I am slightly leaning towards a FAKEish build system - AND I would strongly oppose building a Fable specific one. This would only alienate both potential groups AND it would drain resources that could be used for other more urgent tasks.
@robkuz This isn't for a new build system, this is about a configuration file.
While it would be nice to get rid of the .fsproj file this would break all of the tooling in atom, vscode, and VS
The srcDir option introduces new issues with file ordering.
It still could be useful to have the option an ordered file list in the fableconfig.json like if for whatever reason you have src files in the project that you don't want transpiled with Fable. Synchronization across the two project files would still be an issue that could only be effectively mitigated via tooling, but who wants to write that? 馃槢 (ultimately an ionide-fable plugin to help with fable dev would probably be worthwhile to handle scaffolding, init config files, toggling settings, etc)
Another option for handling config as part of a larger build process is to make a FableHelper module for FAKE
Fable is quite different to the usual F# projects as all refs end up being npm's fsproj doesnt quite fit in at all for anything complex, loads of .net crud when the output here is JavaScript.
Hi @robkuz, you made very good points. I'll try to clarify some of your questions:
fableconfig won't become a build tool_. It would just contain a list of files (and in some cases dll references) to be passed to the F# compiler.fsproj happens to be the standard way to list F# files to be passed to the F# compiler but there's a lot of information there that's not needed for Fable: debugging, optimisation, document generation, platform targets...I think this is also related to Fable philosophy: keep F# as close as possible to JS and don't try to hide the JS ecosystem from .NET developers. In that sense, it'd be better to keep things simple and put the file list directly in fableconfig. But what worries me mostly is:
Maybe a good compromise could be to add the file list to fableconfig and still fall back to projFile if not present (this is actually what happens with code parameter right now, which accepts a code string and has precedence over projFile). Would that be acceptable?
@cloudRoutine ah well, you are right (and I was reading it wrong). yeah than the issue might not be as large as I assumed it to be - nevertheless my conclusion stays: shouldnt all the stuff that is outside of the default toolchain (and with my limited knowledge .fsproj seems to be part of that) again be within a default build system. To me all that is fableconfig.json should belong into a FAKE script (FAKE becoming(?) the default build system for F# and even for quite a bit of the overall .NET eco system).
For example we could have a fable init that could create a skeleton build.fsx which can be changed by the developer
You could probably put all the info you need in a simple npm package.json file to be honest. The fsproj file just doesn't fit fable that snugly, that especially obvious as the fableconfig.json is present.
Also I don't really want the typical F# stuff with Fable projects, fake and paket, JavaScript tools, packages , and scripts are what need to be managed here.
As much as I love FAKE, forcing users to scaffold a FAKE project to compile a simple script would kill Fable. Take into account what's need to start:
.paket/paket.bootstrapper.exepaket.dependencies with at least FAKE listedbuild.cm for Windows usersbuild.sh for Unix usersbuild.fsx itselfAnd...
build for the first time, .paket/paket.bootstrapper.exe downloads Paketbuild.fsx can be runToo much overhead for a "Hello World!" program ;)
@alfonsogarciacaro If it鈥檚 easy to implement the fableconfig that falls back to projFile then I can鈥檛 really see the problem, then it could be a progressive enhancement for uses who want it.
@alfonsogarciacaro thanks for the clarification.
if we make an ionide-fable plugin we could probably get the tooling to work based solely on the data in the fableconfig.json although this could create some conflicts with an existing fsproj file. I'm not sure whether it'd be better to add fableconfig support to forge, or have that just be a part of the ionide-fable plugin. the advantage of building it into forge is that forge could get you up and running with fable right away and could be the common backend for vscode, atom, and w/e other editor might want to use it.
fable it's js, should try to embrace the current default js experience. so node and npm.
It's a transpiler? let's give the same experience as other transpiler, like coffee or babel, so js devs already know that, less stuff to learn. It's not special.
Ideally it can produce easy a npm package, who can be consumed by other js packages.
I think fable shouldnt do the same mistake as F#, to initially try to target only c# or .net devs. JS devs >>>> C# devs >>> F# devs. The js devs want a good language, and already expect to transpile (or babel). Know what? F# is a good language.
so:
coffee, just npmcoffee, just npmi think go all the way npm is nice, like coffee-script or other language, see devDependencies
updating the coffe example:
{ "name": "ethopia-waza",
"description": "a delightfully fruity fsharp varietal",
"version": "1.2.3",
"src": [
"fsharp/waza.fs"
],
"devDependencies": {
"fable": "~1.0.0"
},
"scripts": {
"prepublish": "fable -o lib/ -c src/fsharp/waza.fs"
},
"main": "lib/waza.js"
}
src/fsharp/fable in devDependency as nodejs utility ( .net core, xplat, no mono :smile: )prepublish task to run fable --config package.json -o lib/fable can read src property of package.json
all in babel, so like jsx or http://babeljs.io/docs/plugins/transform-react-jsx/
that's my preferred way, because fable already use babel.
About ides (like visual studio), i think it's easier to improve the nodejstools extensions, because already does everything (prepublish) and should embrace having different language (coffee, fsharp, etc).
If you want to use compiled libraries output in a fsproj, just add a nodejs proj, and a msbuild task to prepublish (or add existing directory as <content path="lib/*"/>, better ihmo)
Having a tool to convert from .fsproj to fableproject.config would be probably enough for people using .fsproj for some reason. Then fable doesn't have to know about .fsproj. Make separate small composable things help keep them simpler.
Survey opened, please vote! https://twitter.com/alfonsogcnunez/status/745536448703520768
@thinkbeforecoding I think a new tool to convert .fsproj files to fableproject.config could create extra work especially since fable can already read .fsproj. It would also have to pass all the arguments and I guess somehow handle the watch command.
My setup is very simple VS2015 with Task Runner kicking off fable (with watch) & webpack (with watch) at start-up. I also have Suave server in the same solution which share the same model file for easy JSON parsing. In one place I have all the code for my entire project. I have some Fake task to publish but it鈥檚 the same sort of thing.
I hope with all the changes this really easy to use work flow won鈥檛 be broken
I think we should use Xebec (or at least Xebec-compatible file format) [as replacement for both fsproj and fableproject.config]. We just need to poke Dave enough to publish anything ;)
The result of the survey is almost a tie and probably doesn't justify removing support for Visual Studio. Some people have also asked about the reasoning behind the question and given choices. I probably haven't explained things well, partly because I wasn't sure yet about the best way to improve the Fable experience and how much work would that involve. I'll try to fix that here:
fableconfig.json so no complicated .fsproj or other tooling would be needed; and 2) hiding types and methods not supported by Fable in the IDE autocompletion.FSharp.Core lib to FSharpAutocomplete, it's necessary to modify the IDE. I was thinking on Ionide because currently it's the most flexible and actively developed F# IDE.fsproj but, as I'm sure the maintainers of any successful OSS project (for me, this is the first one) perfectly know, it takes a lot of commitment to keep a project alive and at one point it's necessary to consider very carefully how to better spend the limited time that can be dedicated to it. I may be wrong, but I'm not sure it's worth to start work on the points above (with the support and documentation overhead it would entail) if this will only benefit a small part of users or may even add confusion to Fable development.All in all, I think it's better to keep Fable as is for now. I really appreciate all your comments and suggestions which help me know better which are the real needs of Fable users.
BTW, thanks to @7sharp9 we have already started porting Fable to dotnetcore. At least this means users won't need to have anything installed to give Fable a try, so the entry barrier will be lower than it is now :)
Focusing on Javascript based tooling and distancing from vs formats will always be a win in something like fable. I think its a shame not to improve on the fsproj format and focus on what fable needs. It is kind over overcomplicated as it is. That was my initial experience with fable I found it a little frustrating to get going, lots of moving parts.
A bit of overly optimistic speculation, but what about using project.json? If .NET Core migration plan after RTM goes back to using .fsproj again, perhaps there will be supported tooling created (and open-sourced) to convert project.json to .fsproj, which may then be used in perpetuity to maintain project parity? There is already conversion from project.json to .xproj so it's not completely unimaginable.
Closing this for now. We'll focus on fixing bugs and improving documentation, samples before trying crazy things like this one ;) Thanks a lot everybody for your insightful comments!
I'm sorry for the late reply here :)
I work daily with Javascript and Typescript, and I'm currently doing some experimentations with Elm. Both have a very simple json config file that can be manipulated directly. And that's how most devs do it. When I started studying F# some weeks ago, the fsproj file was the biggest barrier.
So it seems it's a matter of dev target: if you want to be appealing to current JS / TS / Elm devs, you'll need to let any dependency to fsproj go. If you want to be appealing to people already using Visual Studio or other open source F# tools, you can stay with fsproj.
Targeting the giant group of current front end developers seems the best option for me!
Hi @lucasmreis, thanks for your opinion. I think the same as you and that's why some of us were proposing to list the project files directly in fableconfig.json. However, after deeper consideration and consulting the community, it's become clear that's it's not possible of even desirable to have a clear cut from .NET as it would be very difficult to replace all the tooling and we still need dlls for example for type providers. Also, one of the guidelines of Fable was to bring to JS all the power of F#, not only the language but also its ecosystem.
In any case, I still think fsproj is a big hurdle for lightweight editor users so probably from now we will insist in a workflow using F# scripts or even a F# script to list all files to be compiled, something similar to what Paket does to load dependencies onto F# interactive.
Another late reply. I agree with those that fsproj isn't a good format, and the reasons .NET core moved back to csproj is because the .NET community outside web were lacking behind, so that isn't a good example of why we should stick with fsproj. I also think of fable compiler as a transpiler and focus should be to integrate well with the web frontend community. If one could run the build easy with NPM, that is NPM triggers fable and not fable trigger NPM as I think it is now, then it wouldn't be that hard to integrate with the taskrunner in Visual Studio.
The way I picture it in my head for a larger project is to have a simple F# Suave application, it could be in a standard fsproj console app. In that project I define all the models that I might want to share between client and server. Then I have would like to have a client folder where I keep all the stuff fable should compile, and a simple NPM build script that triggers the fable build of that folder. I picture myself those as plain fsx-files referencing the models in fs-files.
@mastoj it seems like orchestrating that process is easier with a fake build script
@cloudRoutine, I agree that fake should orchestrate the over all build process to build both server side code and client side code to make a complete deploy package, but I think fake should delegate the client side building to NPM as the landscape is now. There might be scenarios where you don't use F# or .NET on the server and in those scenarios forcing fake would be a show stopper for some.
Fable is a command line tool and it's easy to integrate it with npm or FAKE as per user's needs (it's being used like this at moment), so I don't think it requires any particular change for this.
Most helpful comment
Hi @lucasmreis, thanks for your opinion. I think the same as you and that's why some of us were proposing to list the project files directly in
fableconfig.json. However, after deeper consideration and consulting the community, it's become clear that's it's not possible of even desirable to have a clear cut from .NET as it would be very difficult to replace all the tooling and we still needdlls for example for type providers. Also, one of the guidelines of Fable was to bring to JS all the power of F#, not only the language but also its ecosystem.In any case, I still think
fsprojis a big hurdle for lightweight editor users so probably from now we will insist in a workflow using F# scripts or even a F# script to list all files to be compiled, something similar to what Paket does to load dependencies onto F# interactive.