Search code examples
javascriptrubywebpackcodemirrorruby-on-rails-6

Code Mirror not rendering correctly on Heroku Rails 6 app


I recently added the code mirror editor to my rails 6 app. I was able to get everything working fine on my local environment (ubuntu 18.04), but when I deploy the app to heroku the code mirror editor renders the actual text editing area far below the div. It also seems to be filling it with x's. here is a screenshot of it. The x's near the top are actually part of the top editor not shown, and the lower x's are part of the main editor in the picture.

Here is my application.js file:

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("jquery")
import { autocompleteExport } from '../custom/autocomplete';
import { initialize } from '../custom/editor';
import { formatToc } from '../custom/page_display';

window.jQuery = $;
window.$ = $;

$(document).on("turbolinks:load", autocompleteExport.categories)
$(document).on("turbolinks:load", autocompleteExport.search)
$(document).on("turbolinks:load", autocompleteExport.admins)
$(document).on("turbolinks:load", initialize)
$(document).on("turbolinks:load", formatToc)

and here is the editor file that initializes the editors:

import CodeMirror from 'codemirror/lib/codemirror.js'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/markdown/markdown.js'

function initialize(){
    let textArea = document.getElementById('page_edit_content')
    let editor = document.getElementById('content-editor')

    if(textArea && !editor){
        var contentEditor = CodeMirror.fromTextArea(textArea, {
                                                    lineWrapping: true,
                                                    mode: "markdown",
                                                });

        contentEditor.display.wrapper.id = "content-editor"
    }

    textArea = null
    editor = null

    textArea = document.getElementById('page_edit_summary')
    editor = document.getElementById("summary-editor")

    if(textArea && !editor){
        var contentEditor = CodeMirror.fromTextArea(textArea, {
            lineWrapping: true,
            mode: "markdown",
        });

        contentEditor.display.wrapper.id = "summary-editor"
    }

    textArea = null
    editor = null

    textArea = document.getElementById('page_content')
    editor = document.getElementById("new-content-editor")

    if(textArea && !editor){
        var contentEditor = CodeMirror.fromTextArea(textArea, {
            lineWrapping: true,
            mode: "markdown",
        });

        contentEditor.display.wrapper.id = "new-content-editor"
    }

    textArea = null
    editor = null

    textArea = document.getElementById('page_summary')
    editor = document.getElementById("new-summary-editor")

    if(textArea && !editor){
        var contentEditor = CodeMirror.fromTextArea(textArea, {
            lineWrapping: true,
            mode: "markdown",
        });

        contentEditor.display.wrapper.id = "new-summary-editor"
    }
}

export {initialize}

Lastly here is one of the views which is having the issue:

<% @page_title = "New Page" %>

<div class="container form-container">
  <%= form_for @page, url: world_pages_path(params[:world_name]), html: {style: "width: 100%"} do |f| %>
    <%= render 'shared/error_messages', errors: flash[:errors] %> 
    <div class="form-group">
      <%= f.label :title %>
      <%= f.text_field :title, autofocus: true, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :summary %>
      <%= f.text_area :summary, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :content %>
      <%= f.text_area :content, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.submit "Create!", class: "btn btn-primary" %>
    </div>
    <% if params[:category] %>     
    <%= hidden_field_tag :category, params[:category] %>
    <% end %>
  <% end %>
</div>

I'm pretty much at a loss for what could be causing this any help would be greatly appreciated.

edit:

After looking a bit through my browsers devtools, it is looking like the issue may be coming from the css not properly loading in my editor.js file, which is where I import the css files for code mirror.

edit-2:

When I remove the css import statement from the editor.js file, I get the same behavior in development, so I know for sure that that is the issue. If anyone knows the correct way to import styles from node modules that would be very helpful


Solution

  • If anyone runs into something like this in the future, I was able to find an answer.

    The issue was stemming from my misunderstanding of webpack.

    I was directly importing the css from the node module into the editor.js file. I am still not a webpack expert so I couldn't say why this worked locally, but it didn't properly set up the css files to be compiled by webpack in production.

    The fix was to instead create an application.scss file in app/javascript/src. It was in this file I added @import 'codemirror/lib/codemirror.css';

    After doing this I added import '../src/application.scss' to my application.js file so that webpack would know to compile the css.

    Finally, I added <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %> into my application.html.erb layout file which pulls in the css from the compiled files.