miracle2k / webassets

Asset management for Python web development.
BSD 2-Clause "Simplified" License
924 stars 259 forks source link

CoffeeScript --map #218

Open karansag opened 11 years ago

karansag commented 11 years ago

Hi,

I'm trying to use CoffeeScript 1.6.1's --map option to create CS source maps (with django-assets). My strategy has been to subclass Filter, copy over much of the CoffeeScript Filter code, and just add a COFFEE_INCLUDE_MAP option that functions the same way as the COFFEE_NO_BARE option.

This didn't work, and for some mysterious reasons. First of all, does webassets use the system's "coffee" binary? I thought it did, but after uninstalling my system coffeescript and finding the coffee filter still working, it seems it doesn't... How can I upgrade coffeescript?

Also, where should I set my custom filter to be excluded from ASSETS_DEBUG (like the coffeescript filter)?

Thanks!

EDIT: Do the regular webassets options work in django-assets? At first glance, adding COFFEE_NO_BARE doesn't seem to do anything...

karansag commented 11 years ago

Actually, I'm not sure using --map with -p on coffeescript (pipe to stdout) works. The two are mutually exclusive. So maybe this is all a moot point.

miracle2k commented 11 years ago
  1. Like all filters, the CoffeeScript filter will use the path given in the settings (COFFEE_BIN - or the deprecated COFFEE_PATH), and otherwise will simple execute "coffee", assuming it is in the system path. Which binary that is depends on what you have on your path when webassets runs. A source of confusion may also be that the filter doesn't actually run, but the cache is used.
  2. The max_debug_level attribute on the filter specifies if the filter should run in debug.
  3. The option should work in django-assets. However, there was recently a bug report along those lines (https://github.com/miracle2k/django-assets/issues/9), so maybe there is indeed an issue with this...
  4. I'm not very familiar with CoffeeScript, but it is certainly possible to write the filter in a way that does not pipe to stdout, which you then might have to do.
irskep commented 11 years ago

Another issue here is that a source map is actually a separate file with a different type. So if you want to generate a source map for file.coffee, you'll end up with file.js and file.js.map. So now we have two problems integrating this with webassets:

  1. Filters all take one [path|stream] and one output stream, neither of which it controls the paths for. Can't generate two output files for one input file. (I would love to be wrong about this.)
  2. Parent filters (JS minifiers) may combine JS files, invalidating the source maps entirely (this is more the user's problem than webassets's)

So the webassets filter API would have to add functionality to let a filter add a file out of band of the main pipeline.

irskep commented 11 years ago

(I was going to try to tackle this problem, but the API issue is more work than I want to deal with, not being familiar with the library internals.)

coryvirok commented 11 years ago

Has there been any more work done on this front? I'm looking into integrating source maps but the API looks unreasonably complicated for what it's doing.

I am able to generate source maps in a similar manner as @karansag mentioned in their 1st comment but I haven't been able to get around the cache being used instead of the actual file contents.

karansag commented 11 years ago

I've done no more work on this end. As for the cache, @coryvirok, what do you mean? Are you producing a .map file and a .js from a .coffee?

csillag commented 11 years ago

@miracle2k, is there a working example somewhere about creating a filter that generates two output files, from one input? How does one do that with webassets filters?

miracle2k commented 11 years ago

No, this was never considered when designing the filter architecture.

There is no API to provide additional output files via the Bundle - one bundle, one output file. If your filter wants to write out an additional file, you need to make this a filter option (i.e. its then either global, or you initialize the filter by creating an instance of it yourself). I actually think this is probably good enough for a relatively narrow special application like map files.

I mean, the alternative would have to be something like Bundle(more_outputs={'map': 'mapfile'}) which seems like overkill to me.

So you would just create a regular filter, and then write out a second file manually via open(). You should be able to use self.env.resolver.resolve_output_to_path to get the same path targeting that webassets uses for regular output files (or flask-assets/django-assets etc).

@coryvirok mentioned the cache, but I'm not sure if that is a problem. The cache would cause your filter not to run if the input has not changed - so the map file would not be updated; but since the input hasn't change, the output won't change, there will be no need to update the map file.

This would only be an issue the first time you turn on the map creation option of your filter. webassets doesn't know about the extra file your filter wants to create - to it, everything seems to be in order with the Bundle output already existing, so it does nothing. If you delete the bundle output file, it sees that it already has this particular filter run cached and will not run your filter either. So you'd have to disable the cache, remove the .webassets-cache directory, or simply change your source file once to cause your filter to run and the map be created initially.

miracle2k commented 11 years ago

This is the point where I wonder whether the cache should be disabled by default. It's speed benefits for small projects are dubious anyway, it won't usually be used with less/sass anyway etc.

santagada commented 10 years ago

any advances on this? Webassets seems to be the only django asset framework almost ready to support source maps. Support for lesscss source maps and uglifyjs sourcemaps (of bundled sources) would be incredible.

tilgovi commented 10 years ago

I have recent experience combining coffee-generated source maps in javascript. If someone wants to post filter code that generates the map file, I can try to contribute a filter for combining, or a CoffeeBundle or something like this.

csillag commented 10 years ago

Last time I checked, the problem was that the chain of filters filters is (mainly) a one-way street; every filter has one input, and one output. Forking filters (for example, taking source input, and producing separate code and source map outputs) are not supported.

A different approach would be tom contain the sourcemap inside the compiled source files. (Instead of just the usual reference.) This way, we could avoid having to build a filter with two different outputs.

However, this would unnecessarily increase the size of the compiled output, with data which is useless to basically everybody, except developers. (But maybe this could be limited by configuration to debug more, or something like that.)