elucid / ember-cli-redis-proxy

Write index.html to redis on each build
MIT License
4 stars 3 forks source link

manifest.json support #4

Open g-cassie opened 9 years ago

g-cassie commented 9 years ago

Are you interested in a PR to add support for parsing manifest.json and pushing keys from it into REDIS? Maybe this functionality is too custom to be in the addon (and also goes beyond the functionality of ember-cli-deploy)?

In any event I have done this in my own project and would be happy to clean up my code and submit a PR.

To give you an idea of my implementation, I end up doing something like this in REDIS

SET <project_name>:css:vendor:__development__ vendor-12345.css
SET <project_name>:css:app:__development__ <project_name>-12345.css
SET <project_name>:css:vendor:current <project_name>:css:vendor:__development__
SET <project_name>:css:vendor:current <project_name>:css:vendor:__development__
elucid commented 9 years ago

Hmm, I'm not sure I see the advantage of serving all assets out of redis.

The API app has to parse manifest.json in order to determine which assets it can read from redis. Why not just compute the location of the asset on disk and serve from there?

g-cassie commented 9 years ago

I am only storing the fingerprinted filenames in redis, not the actual contents of the assets (the spaces between the keys and values in the REDIS statements I wrote out are kind of hard to see so maybe they gave the wrong impression). I would prefer not to have the backend server read manifest.json from disk and parse the json for every single request in order to determine what files to serve. It also avoids having to add deployment steps to get manifest.json onto the backend server.

Here's a sketch of my setup (this is django/python pseudocode but I'm sure you can do something similar in rails).

template_pre_processors.py

REDIS_VENDOR_CSS_KEY = 'projectname:css:vendor:current'
REDIS_APP_CSS_KEY = 'projectname:css:app:current'

if ENV == 'development':
    STATIC_URL = 'http://localhost:8000/assets/'
else:
    STATIC_URL = 'https://123abc.cloudfront.com/assets/'

def get_css_paths():
    # the keys in the dictionary returned from this function are
    # available to the server template rendering engine
    r = redis.StrictRedis(
        settings.REDIS_HOST_NAME, settings.REDIS_PORT
    )
    keys = [REDIS_EMBER_VENDOR_CSS_KEY, REDIS_EMBER_APP_CSS_KEY]
    current_keys = r.mget(keys)
    paths = r.mget(current_keys)

    # `paths` will now be something like:
    # ['vendor-123abc.css', 'projectname-123abc.css']

    # convert to fully qualified urls
    paths = [STATIC_URL + p for p in paths]

    return {'VENDOR_CSS_PATH': paths[0], 'APP_CSS_PATH': paths[1]}

some_server_rendered_template.html

...
<head>
    ...
    <link href="{{VENDOR_CSS_PATH}}">
    <link href="{{APP_CSS_PATH}}">
    ...
</head>
....
g-cassie commented 9 years ago

@elucid I think I may have made this irrelevant now. I just tried an experiment where I turned off fingerprinting for dev builds and put fully qualified dev urls in index.html.

    <link rel="stylesheet" href="http://127.0.0.1:8000/static/assets/vendor.css">

These work as expected for incremental builds. When you run a production build, it seems that the fingerprint script is smart enough to replace the http://127.0.0.1:8000/static/ with whatever prefix you specify so you end up with a workable url for your CDN.

Is there any other reason you elected to use fingerprinting in development? If not, might make sense to mention this in the readme. The fingerprinting script was adding about 1.3 seconds to every incremental build (I have quite a large base of js assets) so it was a fairly material overhead during development.

elucid commented 9 years ago

Interesting...

Yeah, fingerprinting was only recommended for this reason. I'll take a look tonight and then update the README if it pans out.