Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webpacker Support #232

Closed
waltz opened this issue Feb 3, 2019 · 33 comments
Closed

Webpacker Support #232

waltz opened this issue Feb 3, 2019 · 33 comments

Comments

@waltz
Copy link

waltz commented Feb 3, 2019

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?

@fphilipe
Copy link
Owner

fphilipe commented Feb 5, 2019

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?

@waltz
Copy link
Author

waltz commented Feb 7, 2019

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.

@fphilipe
Copy link
Owner

fphilipe commented Feb 7, 2019

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.

@tillcarlos
Copy link

tillcarlos commented Feb 17, 2019

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" />

@mhanberg
Copy link

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.

@daniel-rikowski
Copy link

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...

@full-of-foo
Copy link

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')}"

@mhanberg
Copy link

mhanberg commented Jul 3, 2019

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

@full-of-foo
Copy link

@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"

@mcmaddox
Copy link

mcmaddox commented Aug 7, 2019

@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.

@mhanberg
Copy link

mhanberg commented Aug 8, 2019

@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.

@mcmaddox
Copy link

mcmaddox commented Aug 9, 2019

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.

@mhanberg
Copy link

mhanberg commented Aug 9, 2019

@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"

@mcmaddox
Copy link

@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.

@mhanberg
Copy link

@mcmaddox I'm glad you got it working.

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

@fphilipe
Copy link
Owner

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

@rubendinho
Copy link

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?

@niedfelj
Copy link

niedfelj commented Apr 1, 2020

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
Copy link

niedfelj commented Apr 1, 2020

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.

@fphilipe
Copy link
Owner

fphilipe commented Apr 2, 2020

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

@marcelolx
Copy link

@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!

@prem-prakash
Copy link

@fphilipe hey, someone else already wrote the code.

Take a look:

leslie-clutter@27c3d82

What do you think? I can help with that.

@prem-prakash
Copy link

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

@olegsfinest
Copy link

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

@gregblass
Copy link

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!

@czj
Copy link

czj commented Apr 27, 2021

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

@notnotjeff
Copy link

notnotjeff commented May 12, 2021

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!

@extendednotes
Copy link

extendednotes commented Jun 2, 2021

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! 👍 Thank you so much for sharing! <3

@onesneakymofo
Copy link

onesneakymofo commented Jul 12, 2021

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

@notnotjeff
Copy link

notnotjeff commented Jul 12, 2021

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

@onesneakymofo
Copy link

onesneakymofo commented Jul 29, 2021

@notnotjeff Sorry, I put this aside for a few weeks and just got around to revisiting.

I carefully went through step by step to no avail. After 3 hours of debugging and crying, I remembered that our mailers were behind Sidekiq.

After restarting Sidekiq, it worked for me. 🙃

@stevecrozz
Copy link

stevecrozz commented Feb 5, 2022

I don't love using extract_css in development as it leaves a trail of debris as I'm working, which is why I use webpack-dev-server. It actually was pretty simple to implement a webpack loader strategy and configure premailer-rails to use it. It would probably need some tweaking to be useful to a general audience, but here's what I have:

class WebpackAssetLoader
  def load(url)
    Net::HTTP.get(URI::HTTP.build(
      :protocol => Webpacker.dev_server.protocol,
      :host     => Webpacker.dev_server.host,
      :port     => Webpacker.dev_server.port,
      :path     => ApplicationController.helpers.asset_pack_path(webpack_path(url))
    ))
  end

  def webpack_path(url)
    URI(url).path.sub(%r{\A/packs/css/}, '').sub(/-\h{8}\.css\z/, '.css')
  end
end

Premailer::Rails.config.merge!(
  :strategies => [WebpackAssetLoader.new],
)

@fphilipe
Copy link
Owner

Thanks everyone for your inputs. I've added a section to the README in 9259af4. I won't be adding explicit support for Webpacker though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests