Skip to content

Instantly share code, notes, and snippets.

@maxivak
Last active November 3, 2024 21:38
Show Gist options
  • Save maxivak/2612fa987b9f9ed7cb53a88fcba247b3 to your computer and use it in GitHub Desktop.
Save maxivak/2612fa987b9f9ed7cb53a88fcba247b3 to your computer and use it in GitHub Desktop.
Webpack, Yarn, Npm in Rails

Webpack in Rails

All code is available in example app - https://github.com/maxivak/webpacker-rails-example-app

Table of Contents

NPM and Yarn

NPM is a package manager for Node based environments. NPM manages dependencies and store its data in file package.json.

Yarn is a package manager that uses NPM registry as its backend. Yarn is like modernized npm. Yarn stores the exact versions of package dependencies in file yarn.lock. Yarn checks package.json file.

Read more:

Webpack and Webpacker

What's wrong with Sprockets

Sprockets - Rails Asset Pipeline. Sprockets is a rails-specific tool, but the frontend evolves by itself and the community prefers to use and create universal tools that don't have any specific limits.

Sprockets (Rails Asset Pipeline) has become obsolete long time ago. It has many problems:

  • Limited support for new frontend tools. For example, with SASS.
  • No support for ES2015 transpiling
  • No support for javascript modules
  • No support for sourcemaps

Webpack

Webpack is a manager for all your front-end code.

Webpacker gem makes it easy to use Webpack to manage application-like JavaScript in Rails.

Webpack provides modularization for JavaScript. Webpack implements a module system as well as a way to translate JavaScript code that doesn't work in any web browser to JavaScript code that works in most web browsers. The whole reason we are using Webpack is because JavaScript has no way to compose source files or package code in any useful way.

Webpacker

Webpacker is a Rails gem that provides integration with webpack module bundler and yarn package manager.

Webpacker coexists with the asset pipeline, as the primary purpose for webpack is app-like JavaScript, not images, CSS. However, it is possible to use Webpacker for CSS, images and fonts assets as well, in which case you may not even need the asset pipeline.

  • NOTE! Using Webpacker you won't need these gems: sass-rails, uglifier, jquery-rails, turbolinks, coffee-rails.

Installation

Webpack with Webpacker

  • Install NPM, yarn in your system

  • Install Webpacker

  • for Webpacker 3.5

Gemfile:

gem 'webpacker', '~> 3.5'
  • for Webpacker 4.x

Gemfile:

gem 'webpacker', '>= 4.0.x'

add package:

yarn add @rails/webpacker@4.0.0-pre.2 
  • install
bundle exec rails webpacker:install

It generates the following file structure

app/javascript:
  ├── packs:
  │   # only webpack entry files here
  │   └── application.js
  └── src:
  │   └── application.css
  └── images:
      └── logo.svg

Webpack without Webpacker in Rails app

You can use webpack in Rails app without Webpacker gem.

Use Foreman.

Webpacker with NPM without Yarn in Rails app

Yarn is not necessary for Webpack. You can replace Yarn with npm for Webpacker gem.

Read more:

Usage

By default, Webpacker builds JavaScript from source files located in app/javascript (a new folder in Rails app) and from node_modules installed via yarn.

  • use in View
= javascript_pack_tag 'application'
= stylesheet_pack_tag 'application'
  • run webpack in development

In development, Webpacker compiles on demand rather than upfront by default.

When in development run bin/webpack-dev-server - this will watch changes to your app and rebuild when required, pushing changes to the browser.

./bin/webpack-dev-server 

# or 
ruby ./bin/webpack-dev-server

Use it in development when:

  • you want live code reloading
  • you have enough JavaScript that on-demand compilation is too slow

Webpacker will automatically start proxying all webpack asset requests to this server. When you stop the server, it'll revert back to on-demand compilation.

Compile assets

When you are ready to compile run

bundle exec rails webpacker:compile

or

rails assets:precompile

new files should appear in public/packs/ folder.

  • Webpacker hooks up a new webpacker:compile task to assets:precompile, which gets run whenever you run assets:precompile. If you are not using Sprockets, webpacker:compile is automatically aliased to assets:precompile. Similar to sprockets both rake tasks will compile packs in production mode but will use RAILS_ENV to load configuration from config/webpacker.yml (if available).

  • compile in production

# compiles in production mode by default unless NODE_ENV is specified
bundle exec rails assets:precompile
bundle exec rails webpacker:compile

Configuration

  • config/webpack directory has corresponding configuration file for each Rails environment.
  • config/webpack/shared.js - file, that is common for all environments
  • config/webpack/environment.js - file responsible for processing settings from config/webpacker.yml.
  • webpacker.config.js - file in the root folder of Rails app, used by Webpack
  • config/webpacker.yml - config file (analog of webpacker.config.js) used by Webpacker

Basic configuration

Webpack needs to know which directories to read from, what transformations it needs to apply to what files, and where to put everything once it’s completed its run.

`package.json'

  • add necessary packages for webpack
{
  "name": "webpacker-rails-example-app",
  "private": true,
  "dependencies": {
    "@rails/webpacker": "3.5",
    "babel-core": "",
    "babel-loader": "",
    "webpack": "3.4.1"
  },
  "devDependencies": {
    "webpack-dev-server": "2.11.2"
  }
}

webpack.config.js

const webpack = require("webpack");

module.exports = {
  context: __dirname + "/app/javascript/packs",

  entry: {
    application: ["application.js"],
  },

  output: {
    path: __dirname + "/public/packs",
  },
};

It takes an input (the "entry" block) from app/javascript/packs folder and producing an output (the "output" block). It will read application.js file from /app/javascript/packs, perform actions required by this file, and output the resulting file to /public/packs/application-__HASH_HERE__.js.

Webpacker is appending hashes to all the assets by default.

  • run in command line
rake webpacker:compile
  • see new file(s) in public/packs/.

  • include javascript in View

= javascript_pack_tag 'application'

Modules

In contrast to Node.js modules, webpack modules can express their dependencies in a variety of ways. A few examples are:

  • An ES2015 import statement
  • A CommonJS require() statement
  • An AMD define and require statement
  • An @import statement inside of a css/sass/less file.
  • An image url in a stylesheet (url(...)) or html (<img src=...>) file.

The webpack compiler can understand modules written as ES2015 modules, CommonJS or AMD. Not all JS files can be used directly with webpack. Webpack supports modules written in a variety of languages and preprocessors, via loaders. Loaders describe to webpack how to process non-JavaScript modules and include these dependencies into your bundles.

Webpack 1 supports two of the most common module formats out-of-the-box: CommonJS and AMD. Webpack 2 supports ES6 module syntax natively, meaning you can use import and export without a tool like babel to handle this for you.

Import ES6 modules

  • import - Statically import the exports of another module.
import MyModule from './my-module.js';
import { NamedExport } from './other-module.js';
  • Example - import bootstrap module from node_modules
yarn add bootstrap@4.1.0
  • app/javascript/packs/application.js
import 'bootstrap/dist/js/bootstrap';

Import CommonJS modules

  • use require
  • Synchronously retrieve the exports from another module.
var $ = require('jquery');
var myModule = require('my-module');
  • require.resolve - Synchronously retrieve a module's ID
require.resolve(dependency: String);

Loaders

List of loaders - https://github.com/webpack/docs/wiki/list-of-loaders

  • babel-loader - transpile from ECMA6 to ECMA5 script
  • file-loader - A file loader module for webpack.
  • resolve-url-loader** - Loader that resolves relative paths in url() statements based on the original source file.

Using third-party libraries

Using third-party libraries that are not CommonJS/AMD/ES6 modules

Shimming

  • Some third party libraries may expect global dependencies (e.g. $ for jQuery). The libraries might also create globals which need to be exported. These "broken modules" can be used with shimming.

imports-loader, exports-loader

  • Some dependencies use a module style in an unusual way that may conflict with webpack. In this case it may help to fool the third-party code that there is no module system at all. Most modules will then fall back to a global variable which you can export using the exports-loader.

  • Use the imports-loader to configure this. Some legacy modules rely on this being the window object. This becomes a problem when the module is executed with webpack where this equals module.exports (in the style of CommonJS). In this case, you can override this with the imports-loader.

  • install loaders

yarn add imports-loader exports-loader
  • Example.

webpack.config.js


module.exports = {
  ...

  module: {
        loaders: [
            {
                test: require.resolve('tinymce/tinymce'),
                loaders: [
                    'imports?this=>window',
                    'exports?window.tinymce'
                ]
            },
            {
                test: /tinymce\/(themes|plugins)\//,
                loaders: [
                    'imports?this=>window'
                ]
            },
        ]
  }

}

  • Examples

  • Broken AMD

require("imports-loader?define=>false!./file.js")
  • Broken CommonJs
require("imports-loader?require=>false!./file.js")

script-loader

  • import scripts globally.

  • If you don’t care about global variables and just want legacy scripts to work, you can use the script-loader.

  • The script-loader evaluates code in the global context, similar to inclusion via a <script> tag. In this mode, every normal library should work. require, module, etc. are undefined.

  • When using the script-loader, the module is added as a string to the bundle. It is not minimized by webpack, so use a minimized version. There is also no devtool support for libraries added by this loader.

  • app/javascript/packs/application.js

require("script-loader!myfile");

noParse

  • Use noParse to include large dists.

  • When there is no AMD/CommonJS version of the module and you want to include the dist, you can flag this module in noParse. This will cause webpack to include the module without parsing it or resolving require() and import statements.

  • This disables parsing by webpack. Therefore you cannot use dependencies. This may be useful for prepackaged libraries.

  • This is also used to improve the build performance.

  • This also means that any feature requiring the AST, like the ProvidePlugin, will not work inside this file. webpack just takes the source code without looking at it.

  • Examples

{
	module: {
		noParse: [
			/XModule[\\\/]file\.js$/,
			path.join(__dirname, "web_modules", "XModule2")
		]
	}
}

read more:

Import from node_modules

You can import styles, javascript from node_modules.

  • import CSS

  • use ~ to tell webpack that this is not a relative import

  • Example

  • app/javascript/packs/stylesheets.sass

@import '~bootstrap/dist/css/bootstrap'

Erb

  • rails-erb-loader - Embedded Ruby (.erb) webpack loader for Rails projects.
  • add Erb support in your JS templates
run bundle exec rails webpacker:install:erb
yarn add rails-erb-loader
  • An example hello_erb.js.erb file will also be added to your project in app/javascript/packs so that you can experiment with Erb-flavoured javascript.

  • webpack.config.js

module.exports = {
    module: {
      rules: [
        {
          test: /\.erb$/,
          enforce: 'pre',
          loader: 'rails-erb-loader'
        },
      ]
    }
  }
};
  • it is possible to link to assets that have been precompiled by Sprockets.

  • Add the .erb extension to your JavaScript file, then you can use Sprockets' asset helpers:

  • app/javascript/packs/example.js.erb

<% helpers = ActionController::Base.helpers %>
const railsImagePath = "<%= helpers.image_path('rails.png') %>"

Javascript compilers

  • if you use import to reference JavaScript dependencies in your script you have to transpile it from ECMA6 to ECMA5 script using Babel. Webpack can do this on the fly by using loaders.

  • Babel is the library used to transpile ES6 to pure Javascript.

  • Install necessary modules

yarn add babel-core babel-preset-es2015 babel-polyfill babel-loader
  • webpack.config.js

const webpack = require("webpack");

module.exports = {
    context: __dirname + "/app/javascript/packs",

    entry: {
        application: ["application.js"],
    },

    output: {
        path: __dirname + "/public/packs",
    },

  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['es2015']
        }
      },
    ]
  },
};

Uglify JS

  • add plugin:
module.exports = {


    module: {
      ...
    }
    plugins: [
        new webpack.optimize.UglifyJsPlugin()
    ]

CSS, SASS

  • install the CSS and SASS libraries and the loaders
yarn add css-loader style-loader sass-loader node-sass extract-text-webpack-plugin
  • basic configuration for CSS, SASS

  • webpack.config.js

...

module.exports = {
    ...
    module: {
        loaders: [
            ...,
            {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: "style-loader" // creates style nodes from JS strings
                    },
                    {
                        loader: "css-loader" // translates CSS into CommonJS
                    },
                    {
                        loader: "sass-loader" // compiles Sass to CSS
                    }
                    ]
            },
            
  • ExtractTextPlugin will handle moving CSS files to the output directory.

  • configuration using ExtractTextPlugin

const webpack = require("webpack");

const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
 ...
 
    module: {
        loaders: [
           ...,
           
          {
            test: /\.css$/,
            loader: ExtractTextPlugin.extract("css!sass")
          }
       ]   
   },
   
  plugins: [
     new ExtractTextPlugin("[name]-[hash].css"),
  ]
  • Store CSS in a separate pack

  • app/javascript/packs/stylesheets.scss


// import css
@import '../src/stylesheets/application';


  • store your CSS/SASS files in app/javascript/src/stylesheets/ folder

  • app/javascript/src/stylesheets/application.scss:

// your css here

.mystyle {
   color: green;
 }


  • include library from node_modules (see Examples below in this post)

// using library from node_modules
@import '~bootstrap/scss/bootstrap';



  • NOTE! In sass or scss you have add a ~ to path, but in JS file you don't need to put ~.

  • use stylesheet in view

= stylesheet_pack_tag 'stylesheets'

Images

Images should be placed in app/javascript/images/.

  • Add app/javascript/packs/application.js:
require.context('../images/', true, /\.(gif|jpg|png|svg)$/i)
  • use images in view - use asset_pack_path method inside the main asset helper:
= image_tag(asset_pack_path('images/logo.svg')) 

or use without Rails helpers

<img src="<%= asset_pack_path 'images/logo.png' %>" />

Import assets from Ruby Engine

Using Webpacker in Rails Engines/gems

Problem:

  • You have a Rails gem which comes with assets (scss, fonts, js) and you want that assets to be available from main Rails app.

Right now webpacker doesn't support Rails engines.

Solutions:

  • option 1. Copy assets from Gem to vendor folder of Rails app
  • option 2. Convert Gem's assets into NPM pkgs

References:

Examples

Basic example - CSS, SCSS

  • CSS

  • pack app/javascript/packs/stylesheets.scss

// css
@import '../src/stylesheets/application.scss'

  • place your CSS code in app/javascript/src/stylesheets/application.scss
.mystyle {
  color: blue;
}
  • include js and css in view (usually in layout file)
= javascript_pack_tag 'application'
= stylesheet_pack_tag 'stylesheets'
  • use CSS styles in view
# app/views/home/index.html.haml

.container
  .mystyle
    I will be blue if webpacker's CSS is working.

  • package.json
{
  "name": "webpacker-rails-example-app",
  "private": true,
  "dependencies": {
    "@rails/webpacker": "3.5",
    "babel-core": "",
    "babel-loader": "",
    "css-loader": "^0.28.11",
    "extract-text-webpack-plugin": "^3.0.2",
    "node-sass": "^4.9.0",
    "sass-loader": "^7.0.3",
    "style-loader": "^0.21.0",
    "webpack": "3.4.1"
  },
  "devDependencies": {
    "webpack-dev-server": "2.11.2"
  }
}


jQuery, jquery-ui

  • add jQuery using NPM packages
yarn add jquery
  • javascript
  • app/javascript/packs/application.js
// jquery

import $ from 'jquery'
global.$ = $
global.jQuery = $



  • make jQuery be seen by other .js files. For global access to jQuery.

  • config/webpack/environment.js:

const { environment } = require('@rails/webpacker')

const webpack = require('webpack');


// Add an additional plugin of your choosing : ProvidePlugin
environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
        $: 'jquery',
        JQuery: 'jquery',
        jquery: 'jquery',
        'window.Tether': "tether",
        Popper: ['popper.js', 'default'], // for Bootstrap 4
    })
)

module.exports = environment
  • use jQuery in view
# app/views/home/index.html.haml

.container
    
  .jquery-test
    jQuery is not yet working.
    
:javascript
  $(function(){
    $(".jquery-test").html("jQuery is working.");
  });
  

jquery-ui

  • add package
yarn add jquery-ui-dist
  • app/javascript/packs/application.js
// jquery
import $ from 'jquery';

global.$ = $
global.jQuery = $


require('jquery-ui');

// jquery-ui theme
require.context('file-loader?name=[path][name].[ext]&context=node_modules/jquery-ui-dist!jquery-ui-dist', true,    /jquery-ui\.css/ );
require.context('file-loader?name=[path][name].[ext]&context=node_modules/jquery-ui-dist!jquery-ui-dist', true,    /jquery-ui\.theme\.css/ );


  • config/webpack/environment.js
const { environment } = require('@rails/webpacker');

const webpack = require('webpack');


// resolve-url-loader must be used before sass-loader
environment.loaders.get('sass').use.splice(-1, 0, {
    loader: 'resolve-url-loader',
    options: {
        attempts: 1
    }
});


// Add an additional plugin of your choosing : ProvidePlugin

environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
        $: 'jquery',
        JQuery: 'jquery',
        jquery: 'jquery',
        'window.Tether': "tether",
        Popper: ['popper.js', 'default'], // for Bootstrap 4
    })
)

const aliasConfig = {
    'jquery': 'jquery/src/jquery',
    'jquery-ui': 'jquery-ui-dist/jquery-ui.js'

};

environment.config.set('resolve.alias', aliasConfig);

//
module.exports = environment;

jquery-ujs

  • Rails-ujs is an unobtrusive scripting adapter for jQuery developed for the Rails framework.

  • add package

yarn add jquery-ujs
  • import in js
  • app/javascript/packs/application.js
...

import {} from 'jquery-ujs';

Read more:

font-awesome

  • add package
yarn add font-awesome@4.7.0
yarn install
  • import in your CSS

  • app/javascript/packs/stylesheets.scss

$fa-font-path: "~font-awesome/fonts";
@import '~font-awesome/scss/font-awesome';

You might have issues with font-awesome in production when it cannot resolve fonts. Be sure to use resolve-url-loader.

  • config/webpack/environment.js

const { environment } = require('@rails/webpacker')

// resolve-url-loader must be used before sass-loader
environment.loaders.get('sass').use.splice(-1, 0, {
  loader: 'resolve-url-loader',
  options: {
    attempts: 1
  }
});

Bootstrap 4

  • add NPM packages
yarn add jquery popper.js jquery-ui-dist jquery-ujs bootstrap@4.1.0 font-awesome
  • package.json
{
  "name": "myprj",
  "private": true,
  "dependencies": {
    "@rails/webpacker": "3.5",
    "webpack": "3.4.1",
    ...
    
    "jquery": "^3.2.1",
    "jquery-ui-dist": "^1.12.1",
    "jquery-ujs": "^1.2.2",
    "popper.js": "^1.14.3",
    "bootstrap": "4.1.0",
    "font-awesome": "^4.7.0"
  },
  "devDependencies": {
    "webpack-dev-server": "2.11.2"
  }
}


  • config/webpack/environment.js
const { environment } = require('@rails/webpacker');

const webpack = require('webpack');


// resolve-url-loader must be used before sass-loader
environment.loaders.get('sass').use.splice(-1, 0, {
    loader: 'resolve-url-loader',
    options: {
        attempts: 1
    }
});

// Add an additional plugin of your choosing : ProvidePlugin
environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
        $: 'jquery',
        JQuery: 'jquery',
        jquery: 'jquery',
        'window.Tether': "tether",
        Popper: ['popper.js', 'default'], // for Bootstrap 4
    })
)

module.exports = environment;

  • app/javascript/packs/javascript.js

// jquery

import $ from 'jquery'
global.$ = $
global.jQuery = $

// bootstrap
import 'bootstrap/dist/js/bootstrap';


// images
require.context('../images/', true, /\.(gif|jpg|png|svg)$/i)


  • CSS

  • app/javascript/packs/stylesheets.scss

@import '../src/stylesheets/application.scss'
  • app/javascript/src/stylesheets/application.scss
$fa-font-path: "~font-awesome/fonts";
@import '~font-awesome/scss/font-awesome';

@import 'variables';
@import '~bootstrap/scss/bootstrap';

@import 'tpl';
  • place your custom variables to customize bootstrap in app/javascript/src/stylesheets/variables.scss
$primary: #4caf50; // change primary color
  • your custom CSS - app/javascript/src/stylesheets/tpl.scss
// your sass here

.mystyle{
  color: $primary;
}

  • include in view
= javascript_pack_tag 'application'
= stylesheet_pack_tag 'stylesheets'

Bootstrap 4 and jquery-ui

  • Bootstrap 4 may have conflicts with jquery-ui.

Tooltips

  • Bootstrap tooltips may not work.
  • Both jQuery UI and Bootstrap use tooltip for the name of the plugin.
  • Use $.widget.bridge to create a different name for the jQuery UI version and allow the Bootstrap plugin to stay named tooltip

Read more:

TinyMCE

  • add package
yarn add tinymce@4.7.13
  • create js file for tinymce

  • app/javascript/packs/tinymce.js


// core
import tinymce from 'tinymce/tinymce'
import 'tinymce/themes/modern/theme'


// plugins
import 'tinymce/plugins/paste/plugin'
import 'tinymce/plugins/link/plugin'
import 'tinymce/plugins/autoresize/plugin'


// skins
require.context('file-loader?name=[path][name].[ext]&context=node_modules/tinymce!tinymce/skins', true,    /.*/ );

  • CSS file for view mode in tinyMCE editor
  • app/javascript/packs/tinymce_style.css
// your css here

  • webpack.config.js
const webpack = require("webpack");

module.exports = {
   ...
   
   module: {
        loaders: [
          ...,
          
          // tinymce
            {
                test: require.resolve('tinymce/tinymce'),
                loaders: [
                    'imports?this=>window',
                    'exports?window.tinymce'
                ]
            },
            {
                test: /tinymce\/(themes|plugins)\//,
                loaders: [
                    'imports?this=>window'
                ]
            },
       ]
    }
};    
            
  • use in view
= javascript_pack_tag 'application'
= stylesheet_pack_tag 'stylesheets'


= javascript_pack_tag 'tinymce'
= stylesheet_pack_tag 'tinymce'



.container

  %h1 tinymce

  %form
    input:
    %textarea.editor
      text here
      <h1>Hello world</h1>


:javascript
  $( document ).ready(function() {
    tinymce_init();
  });


  function tinymce_init(){
    tinymce.init({
      selector: "textarea.editor",

      skin: false,

      plugins: [
        "paste link"
      ],
      toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image myblock",
      relative_urls: false,
      content_css : [
        "#{asset_pack_path('tinymce_style.css')}"
      ],
      protect2: [
              /\<\/?(if|endif)\>/g, // Protect <if> & </endif>
              /\<xsl\:[^>]+\>/g, // Protect <xsl:...>
              /<\?php.*?\?>/g // Protect php code
      ],
      setup: function(editor) {
        
      }
      });
  }


Resources:

elFinder

  • elFinder is a file manager for web, written in JavaScript using jQuery and jQuery UI

  • add packages from github with a specific version

yarn add https://github.com/Studio-42/elFinder.git#2.1.39
  • elFinder depends on jquery and jquery-ui
yarn add jquery jquery-ui-dist
  • see examples how to use jQuery

elFinder themes

yarn add git+https://git@github.com/maxivak/elfinder-theme-bootstrap.git
  • create packs for js and css

  • app/javascript/packs/elfinder.js

// jquery
import $ from 'jquery';

global.$ = $
global.jQuery = $


//
require('jquery-ui');

// jquery-ui theme
require.context('file-loader?name=[path][name].[ext]&context=node_modules/jquery-ui-dist!jquery-ui-dist', true,    /jquery-ui\.css/ );
require.context('file-loader?name=[path][name].[ext]&context=node_modules/jquery-ui-dist!jquery-ui-dist', true,    /jquery-ui\.theme\.css/ );




// elfinder
require('script-loader!elfinder/js/elfinder.full.js');
require('script-loader!elfinder/js/proxy/elFinderSupportVer1.js');
//require('script-loader!elfinder/js/i18n/elfinder.LANG.js');


  • app/javascript/packs/elfinder_style.scss

@import "~elfinder/css/elfinder.full";
@import "~elfinder/css/theme";
@import "~elfinder-theme-bootstrap/css/theme";
//@import "elfinder-theme-material/scss/theme-gray";

  • package.json
{
  
  "dependencies": {
  	...
    "jquery": "3.2.1",
    "jquery-ui-dist": "^1.12.1",

    "elfinder": "https://github.com/Studio-42/elFinder.git#2.1.39",
    "elfinder-theme-bootstrap": "git+https://git@github.com/maxivak/elfinder-theme-bootstrap.git",

  }
}
  • view

<!DOCTYPE html>
<html>
<head>
  <title>File Manager</title>

  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2" />


  <%= javascript_pack_tag 'optimacms/elfinder' %>
  <%= stylesheet_pack_tag 'optimacms/elfinder_style' %>


</head>
<body>

<div id="elfinder"  style="box-sizing: border-box; "></div>

<script type="text/javascript">

    // Detect language (optional)
    var lang = (function() {
        var locq = window.location.search,
            fullLang, locm, lang;
        if (locq && (locm = locq.match(/lang=([a-zA-Z_-]+)/))) {
            // detection by url query (?lang=xx)
            fullLang = locm[1];
        } else {
            // detection by browser language
            fullLang = (navigator.browserLanguage || navigator.language || navigator.userLanguage);
        }
        lang = fullLang.substr(0,2);
        if (lang === 'ja') lang = 'jp';
        else if (lang === 'pt') lang = 'pt_BR';
        else if (lang === 'ug') lang = 'ug_CN';
        else if (lang === 'zh') lang = (fullLang.substr(0,5) === 'zh-TW')? 'zh_TW' : 'zh_CN';
        return lang;
    })();


    // elFinder options (REQUIRED)
    // Documentation for client options:
    // https://github.com/Studio-42/elFinder/wiki/Client-configuration-options
    var opts = {

        transport : new elFinderSupportVer1(),
        resizable : true,
        width : '100%',
        height : '100%',
        url: '/<%=Optimacms.config.admin_namespace%>/media_elfinder',  // connector URL
        lang: lang                         // auto detected language (optional)
    };


    $().ready(function() {
        var rails_csrf = {};
        rails_csrf[$('meta[name=csrf-param]').attr('content')] = $('meta[name=csrf-token]').attr('content');

        // load jQueryUI CSS
        //elFinder.prototype.loadCss('//cdnjs.cloudflare.com/ajax/libs/jqueryui/'+uiver+'/themes/smoothness/jquery-ui.css');

        // Optional for Japanese decoder "extras/encoding-japanese.min"
      /*
       if (window.Encoding && Encoding.convert) {
       elFinder.prototype._options.rawStringDecoder = function(s) {
       return Encoding.convert(s,{to:'UNICODE',type:'string'});
       };
       }
       */

        // Make elFinder
        $('#elfinder').elfinder(opts);

    });



</script>


</body>
</html>

  

Resources

Webpacker example app

Webpack modules:

Webpacker:

Import assets:

@xiaoronglv
Copy link

this article is really helpful. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment