premailer-rails icon indicating copy to clipboard operation
premailer-rails copied to clipboard

Webpacker Support

Open waltz opened this issue 5 years ago • 32 comments

Hello!

I'm using Webpacker on a new Rails project and I would like to use Premailer on my outbound emails.

Is there any current plan to support Webpacker? Would you be open to PR's with a webpack strategy?

waltz avatar Feb 03 '19 00:02 waltz

Hey @waltz!

Is there any current plan to support Webpacker?

Not really. What would be needed for that? Are you processing your CSS with Webpacker? How would that be different? premailer-rails, at least in production, just loads a CSS file. So I assume you're talking specifically about development, aren't you?

fphilipe avatar Feb 05 '19 08:02 fphilipe

You're spot on, I'm processing my CSS with Webpacker and I'd like to use mailer previews in development to take a peek at things before I deploy.

I hacked on it for a little bit and managed to get it working. I built an adapter that looks for a running webpack dev server and asks it for the CSS. If you're interested I could make a PR.

waltz avatar Feb 07 '19 05:02 waltz

I'm not too familiar with the Webpack integration in Rails. As I understand, at least in development, it's completely orthogonal to the asset pipeline, isn't it?

I hacked on it for a little bit and managed to get it working. I built an adapter that looks for a running webpack dev server and asks it for the CSS. If you're interested I could make a PR.

Sure, that would be a great starting point to discuss this further.

fphilipe avatar Feb 07 '19 09:02 fphilipe

Hey guys - thanks for the great work. I have tried all solutions from this post and finally settled with premailer-rails.

I also got this error

could not be loaded by any strategy. (for /packs/mailer-3243232.css)

But I could solve it with this kinda hacky solution. Maybe it helps the next person as well until webpacker support gets included. I threw this into the mailer layout. Works with preview and emails.

<link href="<%= Rails.application.routes.default_url_options[:host]%><%= Webpacker.manifest.lookup("mailer.css") %>" media="screen" rel="stylesheet" type="text/css" />

tillcarlos avatar Feb 17 '19 04:02 tillcarlos

My current project uses webpacker and I was able to get premailer-rails to work by copying the stylesheet_pack_tag from the head of our application layout into the head of the mailer layout.

!!!
%html
  %head
    %meta(content="text/html; charset=utf-8" http-equiv="Content-Type")
    = stylesheet_pack_tag 'application', media: 'all'
  %body
    = yield

Hope that helps.

mhanberg avatar Apr 19 '19 19:04 mhanberg

Both solutions only work if CSS is extracted into separate files, e.g. by setting extract_css to true in webpacker.yml. (By default it is only true for production) Otherwise Webpacker.manifest.lookup and stylesheet_pack_tag just return nil.

It would be nice if premailer-rails supported javascript_pack_tag, at least in development mode. But that would require processing script tags and running Javascript before processing the document...

daniel-rikowski avatar Jun 09 '19 16:06 daniel-rikowski

With Webpacker 4 and extract_css set to true I needed to use the following:

= stylesheet_link_tag "#{root_url.chomp('/')}#{asset_pack_path('email.css')}"

full-of-foo avatar Jul 03 '19 10:07 full-of-foo

@full-of-foo did you try using stylesheet_pack_tag instead of stylesheet_link_tag?

mhanberg avatar Jul 03 '19 14:07 mhanberg

@mhanberg yes, apologies, I see now that the following works:

# in development.rb
config.action_controller.asset_host = 'http://localhost:3000'

# in mailer
= stylesheet_pack_tag "email"

full-of-foo avatar Jul 04 '19 13:07 full-of-foo

@full-of-foo @mhanberg Trying to get this to work now... Do I need to import the mailer SCSS file I want to use into my application.js file? Or does the import statement belong in application.scss instead?

@fphilipe Support for Webpacker really should be standard now that it will be bundled by default in Rails 6. Easier said than done, of course, but I imagine this is going to be a frequently asked question until support is added.

mcmaddox avatar Aug 07 '19 11:08 mcmaddox

@mcmaddox I have a app/javascript/packs/mailer.js that imports a app/javascript/css/mailer.css.

In my app/views/layouts/mailer.html.haml file, i have the following in the head tag.

%head
    %meta(content="text/html; charset=utf-8" http-equiv="Content-Type")
    = stylesheet_pack_tag 'mailer', media: 'all'

I would consider this library to already have Webpacker support.

mhanberg avatar Aug 08 '19 00:08 mhanberg

Strange... I followed the steps you outlined and I'm still not able to get premailer-rails to apply the stylesheet_pack_tag from the layout to the HEAD of my mailer in the iframe when I preview it on http://localhost:3000/rails/mailers.

Manifest.json shows both mailer.js and mailer.scss are being compiled in Webpacker, but only inline styles and adding CSS to a <style> tag in the mailer itself (not the layout) are working right now.

Am I missing a configuration for premailer-rails? I only added the line from the instructions:

Premailer::Rails.config.merge!(preserve_styles: true, remove_ids: true)

I'm also using ERB, not HAML.

mcmaddox avatar Aug 09 '19 13:08 mcmaddox

@mcmaddox

These are the only config that I have set for mail related things I think

# development.rb
config.action_mailer.default_url_options = { :host => "localhost:3000" }
config.action_mailer.asset_host = "http://localhost:3000"

mhanberg avatar Aug 09 '19 16:08 mhanberg

@mhanberg I figured it out: my SCSS file was in the wrong file path & didn't include the stylesheet_pack_tag helper. My mailer also didn't include the layout call (DUH).

Everything is working now as you described. Thanks for your help.

@fphilipe Sorry for wasting your time. Thanks for the truly helpful gem.

mcmaddox avatar Aug 10 '19 04:08 mcmaddox

@mcmaddox I'm glad you got it working.

For the record, I don't think you're wasting anyone's time 😄.

mhanberg avatar Aug 10 '19 04:08 mhanberg

@mcmaddox no worries 😊 As I'm not using this gem at the moment and haven't really used webpacker, I can't help much.

fphilipe avatar Aug 10 '19 06:08 fphilipe

We are running into this issue as well. Is it fair to say that - as @daniel-rikowski alluded to - if one has extract_css set to false, there is no good workaround for using premailer with webpacker?

rubendinho avatar Dec 20 '19 00:12 rubendinho

There are 2 things you need to do to get this to work correctly, first, you need to have something like this in your mailer layout (when not extracting css, it comes as javascript). This will get that javascript tag into the layout, but then premailer strips it out:

    - if Rails.env.production?
      = stylesheet_pack_tag 'mailer'
    - else 
      = javascript_pack_tag 'mailer'

So after you have that, if you set a message header like this:

headers[:skip_premailer] = true if Rails.env.development?

You should be able to see your styles. I'm going to work on a PR that will not strip the javascript tag if it has a special class.

I know that there's a better way to detect if extract_css is true or false, rather than depending on the Rails.env. Will add that when I find it.

Also, instead of adding that skip_premailer to the headers in the mailer action, you could also setup a before_action in the mailer or set the default headers in your development.rb config like this:

  config.action_mailer.default_options = {
    skip_premailer: true 
  }

Of course, all of this just disables premailer in development, so it's not going to at this point show you exactly what is produced in production vs dev enviroments, but at least allows you to use hmr/inline styles AND preview emails.

niedfelj avatar Apr 01 '20 17:04 niedfelj

Looks like premailer also accepts this option, which could be put in an initializer:

Premailer::Rails.config.merge!(remove_scripts: false)

I think the right way forward @fphilipe would be to add another "strategy" that works with webpacker .js files, to get the CSS out of what's generated there.

niedfelj avatar Apr 01 '20 18:04 niedfelj

@niedfelj, happy to accept a PR for this! 😊 👍

fphilipe avatar Apr 02 '20 05:04 fphilipe

@mcmaddox

These are the only config that I have set for mail related things I think

# development.rb
config.action_mailer.default_url_options = { :host => "localhost:3000" }
config.action_mailer.asset_host = "http://localhost:3000"

I've made it working including the asset_host config, thanks!

marcelolx avatar May 20 '20 19:05 marcelolx

@fphilipe hey, someone else already wrote the code.

Take a look:

https://github.com/leslie-clutter/premailer-rails/commit/27c3d82b12272404614004eedcb039b1534228aa

What do you think? I can help with that.

prem-prakash avatar Jul 06 '20 16:07 prem-prakash

@niedfelj I could not move forward with this PR, could you give some help here?

prem-prakash avatar Jul 06 '20 18:07 prem-prakash

Hi there, any plans to merge the pull request? Webpacker has been bundled with rails for quite some time now. Cheers

olegsfinest avatar Dec 13 '20 20:12 olegsfinest

Just checking in here to see what the best practice is to use premailer with webpacker. I can't get it working for the life of me, no matter what I try from any comment above.

Thank you!

gregblass avatar Apr 19 '21 21:04 gregblass

We have been able to keep premailer active in development since today on our app, in mailer preview.

Webpacker 6 (Webpacker 5) on Rails 6.1

czj avatar Apr 27 '21 09:04 czj

Thought I'd post what worked for me, it's basically a mix of the methods gathered from here. I'm on:

  • Rails 6.1
  • Webpacker 5.3.0
  • Premailer Rails 1.11

Steps:

  1. Create a file for the mailer css: app/javascript/stylesheets/mailer.scss
// Entirety of your css here
* {
  margin: 0;
  padding: 0;
}
  1. Import that mailer css in a javascript pack file: app/javascript/packs/mailer.js
import "../stylesheets/mailer";
  1. Set extract_css option to true in your webpacker.yml so webpacker builds a separate css file to hook into: config/webpacker.yml
...
extract_css: true
...
  1. Added stylesheet_pack_tag to mailer layout file <head> tag to load the css file: app/views/layouts/mailer.html.erb
<!DOCTYPE>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Title</title>
    <%= stylesheet_pack_tag 'mailer' , media: 'all' %>
</head>
  1. Setup action mailer config: config/environments/development.rb:
Rails.application.configure do
  # ...
  config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
  config.action_mailer.asset_host = "http://localhost:3000"
  # ...
end
  1. And of course make sure you've installed the premailer-rails gem (with initializer) following its documentation

Hope this can help others!

notnotjeff avatar May 12 '21 14:05 notnotjeff

Thought I'd post what worked for me, it's basically a mix of the methods gathered from here. I'm on Rails 6.1 Hope this can help others!

Exactly what I was looking for! :+1: Thank you so much for sharing! <3

extendednotes avatar Jun 02 '21 15:06 extendednotes

It is still not working for me. I'm not sure what I'm doing incorrectly.

I've:

  1. Created an initializer (don't think that's necessary)
  2. Created a mailer.css file under javascript/stylesheets
  3. Created a mailer.js pack under javascript/packs
  4. Set extract_css: true on config/webpacker.yml
  5. Set up the config/environment/development.rb
  6. In my mailer layout, I've either used stylesheet_pack_tag or javascript_pack_tag with no results.
  7. Made sure I had premailer-rails installed, haha

My Rails version is 5.2.8 with Webpacker 5.2.1

onesneakymofo avatar Jul 12 '21 17:07 onesneakymofo

It is still not working for me. I'm not sure what I'm doing incorrectly.

I've:

1. Created an initializer (don't think that's necessary)

2. Created a `mailer.css` file under `javascript/stylesheets`

3. Created a `mailer.js` pack under `javascript/packs`

4. Set `extract_css: true` on `config/webpacker.yml`

5. Set up the `config/environment/development.rb`

6. In my mailer layout, I've either used `stylesheet_pack_tag` or `javascript_pack_tag` with no results.

7. Made sure I had `premailer-rails` installed, haha

My Rails version is 5.2.8 with Webpacker 5.2.1

I'm on Rails 6 and I haven't tried on Rails 5 so there might be some fundamental difference there potentially (I've updated my original post with all my version specs). Here's a few things to try though:

For the extract_css parameter make sure it's being set for the environments you need it to be, and if you put it under default so that it works in all environments make sure you aren't overwriting it later in the file in the environment specific sections.

When running the server is Webpack compiling everything correctly? Do you see it creating a separate mailer.css file? Something like:

css/mailer.css  3.16 KiB                mailer  [emitted] [immutable]  mailer

And are your styles being imported correctly into that file?

Are there any differences between your mailer.js and mine?

I think(?) it has to be a stylesheet_pack_tag because the gem looks for linked stylesheets

I believe you do need the initializer from the gem documentation so it will run automatically on outgoing emails

notnotjeff avatar Jul 12 '21 22:07 notnotjeff