How to load packages installed by `bundle` in webpack? - javascript

In a Ruby on Rails application, how can we require or import a package which was not installed via npm or yarn, but via bundle?
I tried:
//= require package-name
But that doesn't seem to work with webpacker.
require("package-name") doesn't work either (because it is not found in node_modules).

For normal Rails environment, you can use normal directory path if you want to require some files.
Suppose your assets folder looks like this
├── application.js
└── something.js
and you want to require something.js then you just need to write
//= require ./something.js
to your application.js
For a package that you manually place somewhere, then you have to add the place of packages to Rails.application.config.assets.paths
If you are using Rails v5, you can check the config/initializers/assets.rb to see the magic of loading node_modules happened

I have no webpack experience and no solution for your problem.
what about this
https://webpack.js.org/loaders/bundle-loader/
as I read in the documentation paths chapter
Paths
By default, Webpacker ships with simple conventions for where the JavaScript app files and compiled webpack bundles will go in your Rails app, but all these options are configurable from config/webpacker.yml file.
The configuration for what webpack is supposed to compile by default rests on the convention that every file in app/javascript/packs/*(default) or whatever path you set for source_entry_path in the webpacker.yml configuration is turned into their own output files (or entry points, as webpack calls it). Therefore you don't want to put anything inside packs directory that you do not want to be an entry file. As a rule of thumb, put all files you want to link in your views inside "packs" directory and keep everything else under app/javascript.
Suppose you want to change the source directory from app/javascript to frontend and output to assets/packs. This is how you would do it:
# config/webpacker.yml
source_path: frontend
source_entry_path: packs
public_output_path: assets/packs # outputs to => public/assets/packs
Similarly you can also control and configure webpack-dev-server settings from config/webpacker.yml file:
# config/webpacker.yml
development:
dev_server:
host: localhost
port: 3035
If you have hmr turned to true, then the stylesheet_pack_tag generates no output, as you will want to configure your styles to be inlined in your JavaScript for hot reloading. During production and testing, the stylesheet_pack_tag will create the appropriate HTML tags.
The asset-pipeline loads the files from the path defined with Rails.application.config.assets.paths
This is the output from my rails console
["/home/fabrizio/Documents/Sublime/Rails/surfcheck/app/assets/config",
"/home/fabrizio/Documents/Sublime/Rails/surfcheck/app/assets/images",
"/home/fabrizio/Documents/Sublime/Rails/surfcheck/app/assets/javascripts",
"/home/fabrizio/Documents/Sublime/Rails/surfcheck/app/assets/stylesheets",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/font-awesome-rails-4.7.0.2/app/assets/fonts",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/font-awesome-rails-4.7.0.2/app/assets/stylesheets",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/jquery-rails-4.3.1/vendor/assets/javascripts",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/coffee-rails-4.2.2/lib/assets/javascripts",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/actioncable-5.1.4/lib/assets/compiled",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/actionview-5.1.4/lib/assets/compiled",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/turbolinks-source-5.0.3/lib/assets/javascripts",
#<Pathname:/home/fabrizio/Documents/Sublime/Rails/surfcheck/node_modules>,
#<Pathname:/home/fabrizio/Documents/Sublime/Rails/surfcheck/vendor>,
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/bootstrap-sass-3.3.7/assets/stylesheets",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/bootstrap-sass-3.3.7/assets/javascripts",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/bootstrap-sass-3.3.7/assets/fonts",
"/home/fabrizio/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/bootstrap-sass-3.3.7/assets/images"]
When you do a require in your application.js or application.scss, sprockets will use the ruby require statement to search that file in the predefined paths.
In case of a GEM, it will find it in the .rbenv/version/yourversion folder.
My approach to solve this problem would be to include those files from the gem that you need for you front end app in the correct folder, so just visit the repository from the GEM and copy paste those file in the correct location.
I know this is not a solution to your problem, but I just wanted to help you out.
Bye
Fabrizio

Related

React & Webpack - Project set up for multi page application

I'm starting up a react project (using create-react-app) which will have multi "one page" components within. So, I assume, the directory structure for development would look like below:
/Project
/node_modules
/public
/src
/components
/layout
/popup
...
/pages
/dashboard
index.js
/profiles
index.js
...
If I build the project without any modification, it would bundle all the source code and resources under one directory. Well, that's not going to work for what I am trying to do for this project. I need to have different bundles for each page. So the bundles under the /public folder should look something similar to the following structure:
/Project
...
/build
/dashboard
/static
/css
/js
/media
index.html
/profiles
/static
/css
/js
/media
index.html
...
I looked at "Code Splitting" in webpack documentation. There's a good example with different entry points but I couldn't adapt it. How can I achieve the desired setup with webpack and react?
I would suggest to use React code splitting, using React Loadable, no need to modify Webpack configuration.
https://reactjs.org/docs/code-splitting.html
May be it is late to answer but I was facing the same issue and found a simple solution that I wanted to share.
I followed these steps:
Multiple entry points in webpack for each page
dynamic output bundle names for each entry point
Multiple html output files with different filenames using HtmlWebpackPlugin, also define particular chunks (bundles),
new HtmlWebpackPlugin({ filename: 'index.html',template: './src/index.html' ,chunks:['page1']})
Each template for each html page will have one div with particular id lets say root which is used by react app to render its app on dom.
Now every js entry point for each page will have
ReactDOM.render(<Page1 />, document.getElementById("root"));
Have a look at the Webpack docs on Multiple Entry files
And have a look at the examples in webpack's github

Incorporating vendor js files (from wrap bootstrap) into Rails 4

I'm struggling to understand how to incorporate vendor js assets into my Rails 4 application.
My app uses bootstrap. The vendor files include a js file, called npm.js. That file has the following in it:
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')
In my app/assets/javascript folder, I have a file called application.js. In that file, I have:
//= require npm
In my console inspector, I can see an error with the incorporation of the npm file. The error message is:
npm.self-f66d504….js?body=1:2 Uncaught ReferenceError: require is not defined
I think it might be something to do with the ../.. references that are set out in the npm.js file.
Does anyone know how to adapt this for use in rails 4 (hosted on heroku)?
Thanks very much.
Those require(...) statements in your JS are in the CommonJS format (hence the comment at top) and are commonly used in Node.js but aren't supported in browser environments which is why you're getting that error in the inspector.
One option is to use Browserify with Grunt to link and compile each of those JS files into a single npm.js (though I'd recommend a different name) file. Are you already using browserify_rails, Grunt, or a similar tool to manage your JS files?
If you haven't worked with Grunt/Browserify, or if the above statement is unclear, it's probably best and simplest to just stick to the Rails asset pipeline:
So application.js would become:
//= require('<path>/js/transition.js')
//= require('<path>/js/alert.js')
//= require('<path>/js/button.js')
//= require('<path>/js/carousel.js')
// etc...
Instead of:
//= require npm
And this should generate equivalent JS to your sample above.
Finally, make sure <path> is included in your config.assets.paths config variable.

Ember build output (dist folder)

In Ember JS project, we have package.json (for NPM managed) and bower.json (Bower managed) where we have all our dependencies/devDependencies (e.g. bootstrap, jquery, ember, etc)
Now these get downloaded from their respective registries and get downloaded locally into node_modules/bower_components folder.
Now my question is while these folders (node_modules/bower_components) contain a lot of code dependencies, when we do a build, I see some code in the "dist" folder.
I want to understand what actually goes into this dist ?
I see things like vendor.css, vendor.js, myappName.css, myappName.js, etc
So how do these get constructed and what code actually goes inside these ?
Is it also base on what we have in our package/bower json config files ?
Or is it based on what we have in ember-cli-build.js ?
What is put under /dist should be everything you need to publish your application. Components from bower_components are typically loaded via app.import() in ember-cli-build.js and stuff from node_modules by addons you've installed (which ember-cli picks up automatically).
Here is a quick rundown of the files.
index.html --> Generated by ember-cli upon project creation
* --> Everything from /public
assets/
appName.css --> All css from under /app
appName.js --> All js and compiled templates from /app
vendor.css --> Any css imported from bower_components/node_modules (via ember-cli-build.js)
vendor.js --> Any js imported from bower_components/node_modules (via ember-cli-build.js)
test-*.js --> Test loader/support for ember-cli if you've run "ember test"
Most files also come with sourcemaps as .map which you can exclude when publishing the site.
As you said, the dependencies you declare in your bower.json and package.json get downloaded to bower_components and node_modules
When you do you an ember build command what happens is that all the code you decide to import in your ember-cli-build.js will get dumped to the vendor.js / vendor.css file. All your application code (templates/routes/components/controllers/services) will be placed in my-app-name.js. All your application styles will go to the my-app-name.css file. All these files will be placed in the dist directory so that you can deploy it.
See this sample ember-cli-build.js file:
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
//CSS - Content of these files will go to "vendor.css"
app.import('vendor/css/bootstrap.css');
app.import('bower_components/datatables/media/css/jquery.dataTables.css');
app.import('bower_components/datatables/media/css/dataTables.bootstrap.css');
app.import('vendor/css/plugins/toastr/toastr.min.css');
// Javascript - Content of these files will go to "vendor.js"
app.import('vendor/js/bootstrap.js');
app.import('vendor/js/plugins/metisMenu/jquery.metisMenu.js');
app.import('vendor/js/plugins/toastr/toastr.min.js');
app.import('bower_components/datatables/media/js/jquery.dataTables.js');
return app.toTree();
};
The CSS imports will go to the vendor.css file and the JS imports will go to the vendor.js files.
The content of your my-app-name.css comes from the app/styles folder.
If you do ember build --environment production the ember build process will also fingertring your assets (append a hash at the end of the filename and generate an appropriate reference in the index.html file).

Proper way to require external js and css libraries in ember js?

I have been playing around with ember 1.13 and I can see that in some online tutorials they require js and css via index.html while some uses ember-cli-build.js or brocfile.js for older versions. I find it requiring properly when I use ember-cli-build.js but then I am not sure what exactly the use of index.html
It depends.
If you have a ember-cli-plugin it will add the files to the vendor files by itself normally. Like with ember-cli-materialize.
If you are installing a random bower package like Ladda, you would need to add the files you need manually to ember-cli-build.js:
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
});
app.import('bower_components/ladda/dist/ladda-themeless.min.css');
app.import('bower_components/ladda/dist/spin.min.js');
app.import('bower_components/ladda/dist/ladda.min.js');
return app.toTree();
};
This will then be merged into your vendor.css and vendor.js which are linked to from index.html.
Also when you build the app the bower_components won't be available unless you've explicitly included something, so you cannot just link to them from index.html. It would also be a waste of network resources to include files separately. You shouldn't have to include anything in index.html unless it's an external resource.
brocfile.js is the old name for ember-cli-build.js since they've stopped using broccoli. Just use the newer one.

Non global coffee script and asset pipeline

I have a coffee script user.js.coffee, that is only used in certain views. I achieved this by using the following answer:
https://stackoverflow.com/a/6795533/784318
Now I have excluded the script from the application.js. I also removed the //= require_tree . entry.
So my file is available here: http://localhost:3000/assets/user.js however, when I deploy this to the server the assets will be combined in one application.js so how can I make sure that the user.js will be available on production like so: http://myserver.com/assets/user.js?
In environments/production.rb (or the environment you need precompile to occur) uncomment or add this file to the precompile array:
# environments/production.rb
config.assets.precompile += %w( user.js )
Other entries might be already present, just add any other file that you need to access separately.
This file will not get compiled in one big application.js file and will be accessible separately as user.js
You can try putting your user.js file to the public folder of your application directly and configure your asset pipeline to exclude it from the "zipping" process.

Categories