I'm trying to use require.ensure to cause Webpack 2 to create separate bundles containing polyfills for older browsers.
I was of the understanding that the following code would cause a new bundle whatwgFetch to be created and loaded:
require.ensure([], (require) => {
require('whatwg-fetch')
}, 'whatwgFetch')
Webpack outputs that only one bundle is created, and when I inspect it I can see the whatwg-fetch module has been included within.
My assumptions are based on the Webpac 2 code splitting guide: https://webpack.js.org/guides/code-splitting-require/
What else should I do to cause webpack to create and load a separate bundle?
I was importing the whatwg-fetch elsewhere in the application, which was causing webpack to correctly bundle it in with the rest of the code, in one single bundle.
Removing these extra imports caused it to work correctly
Related
How can I output the javascript file from Parcel, include this javascript file in Rails app/assets/javascripts/application.js, and ideally get it working with hot module reloading?
Alternatively, is this a bad approach, and do you recommend something more streamlined, that lets me use mostly traditional .html.erb Rails templates but sprinkle in ReactJS UI components here and there?
I was able to do this perfectly in Parcel 1 but I am finding that the setup is quite different in Parcel 2.
I am using the traditional Rails 5 application.html.erb templating.
My attempt so far with Parcel 2 has been to use the library tutorial in the Parcel documentation. I can mount the simplest React component to my Rails app but then if I try to import anything I get errors like require is not defined, and HMR is not working.
I'm not sure how much context to provide for this question. But if it helps, my previous setup with Parcel 1 was to have a separate npm app at the root folder (next to the Rails /app folder) which output a dist/index.js file using the npm script parcel start app/index.jsx --out-dir dist --public-url /assets/dist. This was added to the Rails assets via config.assets.paths << Rails.root.join('frontend') and included in app/assets/javascripts/application.js .
Now for Parcel 2 I removed the include in application.js and added <script type="module" src="/assets/dist/index.js"></script> in application.html.erb
There are two errors you're seeing that I might be able to help with:
Runtime errors like require is not defined. This would be expected if you set up parcel to output your javascript as a library target (as you indicated). Libraries are typically npm packages that are consumed by other projects. In this context, parcel will output a commonjs bundle (including require-based imports) that's intended to be processed by another bunder (maybe parcel again, or webpack) before it's ready to be executed in a browser. You probably want to build your javascript with a browser target instead, so that all dependencies are included without require statements to other packages.
Assuming your package.json for the parcel project currently looks similar to the the library tutorial, the way you'd do that would be to remove the "main": "path-to/my-root-javascript.js" field, and change the build script to parcel build path-to/my-root-javascript.js. There's also a bunch of ways to customize this - see the targets documentation.
HMR not working. If parcel is only in charge of bundling your javascript (and rails is building your html from templates), then the "normal" way that parcel does HMR won't work. This "normal" way would involve parcel injecting an HMR script in the html file that's its responsible for building and serving. But if Rails is taking care of the HTML, parcel can't do this automatically. Perhaps there is a way to configure rails to watch when parcel rebuilds the js bundle, and refresh the page?
This might be a bit of an onion-peeling exercise - it's hard to say if the above suggestions will solve it all end-to-end. If you can post a minimal reproduction of the issue (maybe a simplified version of your ruby + parcel project?) on github that shows the problem, I'm happy to troubleshoot it further.
I have a Rails 5.2.1 app and would like to integrate Vue in a piecemeal fashion; I have everything working nicely in development with Foreman starting Rails and the webpacker dev server together.
I wrapped everything inside the body tag in a div with id="vue-app", and mount the app using the following in packs/app.js:
document.addEventListener('turbolinks:load', () => {
const app = new Vue(Vue.util.extend({ i18n }, App)).$mount('#vue-app')
})
This works fine in development - I can add vue directives on any element and drop in my components wherever I need to. However, when running the same thing in production mode (after asset precompilation), the app fails to mount to #vue-app and just replaces it with an HTML comment. Vue itself is loading fine, compilation appears to be fine, everything is being found - it just silently fails to mount.
I've been researching for a couple of hours, and can't find anything besides duplicates of this: Vue.js app works in development but not mounting template in production with Rails 5.2.0 / Webpacker - blank screen with no errors in console
His solution was to change the mounting to a render function on a new element, but ends with 'I still don't know how to use DOM as template with Vue in production though.'
It severely diminishes the appeal of Vue if it can't be mounted on existing elements, so I'm curious if it is at all possible to use a DOM template in production with Rails/webpacker?
I think I've solved my own problem - I believe it was caused by a mismatch between dependencies in package.json. I may have inadvertently messed it up while I was working on other aspects of the Vue app. I generated a new Rails application, added Webpacker and Vue, confirmed it worked with DOM templates in production with compiled assets, and then copied the versions out of that clean package.json into my existing app.
So, using Rails 5.2beta (gem install rails --pre), if you create a new app via rails new myapp --webpack=react... how would I go about incorporating Lodash into my flow from there?
I've mucked around with babel-plugin-lodash and lodash-webpack-plugin to no avail.
The compile doesn't fail if I do something like import { _pick, _map } from 'lodash/array'; ... but those variables are undefined when trying to use them.
I'm a bit lost as I'm both new to webpacker & webpack, and a lot of existing examples seem to target an older version of webpack?
Anyway, thank you for any help...
UPDATE:
Ok, looks like you can just do import map from "lodash/map"
So where are you trying to use lodash from? By this I mean are you sure the files are getting compiled / processed by Webpacker, or are they getting processed via the Asset Pipeline?
On my webpacker project I realized that there's a problem: that yes, regular old Javascript compiled with the Asset Pipeline won't know about the NPM Modules included via Webpack. (or at least the require statements wouldn't work).
Because of this I made a hard rule: all javascript goes where webpacker expect it (app/javascript) and no Javascript goes in app/assets. We only use the asset pipeline for CSS (which works great in our case, as I still don't think React - our frontend framework of choice - has a good story around site wide CSS).
I'm trying to fully replace the rails asset pipeline with a webpack based pipeline. I've got the dev setup with the webpack-dev-server and hot reloading etc all working beautifully. Now what I'm trying to achieve is a compilation step for production that would mimic how rails compiles assets (digesting / generating a compatible manifest.json file) such that I can still use helpers like javascript_include_tag etc. This is where I'm stuck.
I've read lots of tutorials on using webpack with rails, but they all end up writing their own view helpers to load the assets. I'm trying to avoid this because I don't want extra overhead or for devs to need to understand a different pipeline. I also want config like asset_host= to work out of the box for using a CDN etc.
Ultimately, what I want is something similar to gulp-rev-rails-manifest that generates a rails-asset-pipeline compatible manifest file on compilation, but I haven't found a plugin (yet) that exists for Webpack. So...
is it possible to run a webpack build through a gulp stream using webpack only (ie not using gulp-webpack) so I can use the above gulp plugin. The reason I don't want to use gulp-webpack is that it takes over your entries / output etc and I find that whole setup confusing since this all already exists in webpack.config
Or
Does anyone have any decent resources on writing plugins for Webpack. It seems a bit of a black box to me and the official site has a menu section for "How to write a plugin" but it's not actually a link to anything.
Or
Is there actually a plugin that will do exactly this and I don't know how to search properly on the interwebs.
Any help is greatly appreciated :)
Running webpack in a gulp task is very simple:
var webpack = require('webpack');
var webpackConfig = require('./webpack.config');
gulp.task('webpack', function(done) {
webpack(webpackConfig, function(err, stats) {
done(err);
});
});
Note that the stats object provided to the webpack callback contains information about all assets emitted by webpack, so you could potentially use it to generate your own manifest.
Here are a few webpack plugins you might find useful:
https://github.com/sporto/assets-webpack-plugin
https://github.com/danethurber/webpack-manifest-plugin
https://github.com/diurnalist/chunk-manifest-webpack-plugin
While there is no official tutorial on how to create a plugin, there's still a Plugin API doc that describes the different interfaces your plugins can hook into. The webpack source and github contain a lot of webpack plugin examples.
Here's a very simple plugin that just logs assets:
module.exports = function() {
this.plugin('done', function(stats) {
console.log(stats.toJson().assets);
});
};
Bundle works fine but does not update no matter what, even when I change the bundle structure by altering sequence of "Includes", adding "?xxxx333" [some dummy version] to file names, deleting files name from the includes. Changed contents of files. I even tried changing file name of an includes javascript file in the bundle includes, then renamed the file name in actual folder. App threw "File not found" error.
Not sure what to do. The bundle is just stuck and wouldn't change. I browsed around to find solutions. Others people experienced similar issues in the past but their solutions didn't work.
This is just crazy, I have change SriptsBundle to Bundle (so that files are not automatically mimified), added BundleTable.EnableOptimizations = false. Turned off the machine several times. Changed file names... nothing has worked. I guess my last resort is to get rid of this bundling and go back to explicit includes in files. I am just getting tired of these half cooked APIs being thrown into the market.
Any ideas?
Finally, what seemed to work is this :
bundles.Clear()
bundles.ResetAll()
Only issue now is I can't stop the bundling from mimifying everything despite the fact I am calling Optimization = false.
I had a similar problem. In my situation, I had a CSS file that changed (alongside the minified version) but the bundle would not update.
I noticed that there was a CSS mapping file also included in the project (even though the project on my development environment was set up to minify the CSS file but not generate a mapping file). Deleting this mapping file actually caused the bundle to refresh correctly.
I also had another issue once where I had a CSS file that was referenced in a script bundle but a minified version of that file did not exist. Even though I had the "EnableOptimizations" flag set to false in the bundle code, for some reason, the absence of that minified CSS file caused the script bundle reference in the MVC view to not update, even though it referenced the actual CSS file, not the minified version. Even after I got this working by including a minified version of that CSS file in the project, the reference in the MVC view still pointed to the original CSS file.
Long story short, the bundling code has some weird quirks (or features?) so you might have to try different combinations of things to get it to behave correctly.