Installing Modernizr with Yarn on Rails - javascript

I am trying to install Modernizr with Yarn in Rails. I do 'yarn add Modernizr' and it gets added to the .node-modules directory. However, I can't figure out how to reference it properly from Rails.
I have added //= require modernizr/src/Modernizr to application.js. But I'm not sure that's the right reference because I get the following error:
Uncaught ReferenceError: define is not defined
Do I need to somehow build the Modernizr library. Does yarn not do that? I'm somewhat new to this and struggling to understand the relationship between webpacker, yarn, and rails and how to properly build and add libraries to rails with yarn. The tutorials all make it seem as though it's as simple as 'yarn add xxx' but I seem to be missing something. Thank you.

What you're looking for is the webpacker gem, which ships by default with Rails 5.1+ but can be used with Rails 4.2+. Get that set up, then follow these steps to get a custom Modernizr build running in your Rails app:
Loader
Install the loader for modernizr:
$ yarn install webpack-modernizr-loader
Modernizr Configuration
Download your desired modernizr config from the modernizr site. Visit a link like this:
https://modernizr.com/download?-appearance-backgroundblendmode-backgroundcliptext-backgroundsize-bgpositionxy-borderradius-boxshadow-boxsizing-canvas-canvastext-cssgradients-csspointerevents-fontface-generatedcontent-inputtypes-lastchild-mediaqueries-multiplebgs-opacity-svg-touchevents-setclasses-dontmin-cssclassprefix:mod_
Then configure your build, click "Build" in the upper right-hand corner, and download "Command Line Config".
Then convert it from JSON to a module and save it as config/webpack/.modernizrrc.js (note the leading period in the filename), like so:
"use strict";
module.exports = {
minify: false,
options: [
"setClasses"
],
"feature-detects": [
"test/canvas",
"test/canvastext",
"test/inputtypes",
"test/svg",
"test/touchevents",
"test/css/appearance",
"test/css/backgroundblendmode",
"test/css/backgroundcliptext",
"test/css/backgroundposition-xy",
"test/css/backgroundsize",
"test/css/borderradius",
"test/css/boxshadow",
"test/css/boxsizing",
"test/css/fontface",
"test/css/generatedcontent",
"test/css/gradients",
"test/css/lastchild",
"test/css/mediaqueries",
"test/css/multiplebgs",
"test/css/opacity",
"test/css/pointerevents"
]
};
Custom Configuration
Next, create a custom webpack config file as config/webpack/custom.js:
const path = require("path");
module.exports = {
module: {
rules: [
{
loader: "webpack-modernizr-loader",
test: /\.modernizrrc\.js$/
}
]
},
resolve: {
alias: {
modernizr$: path.resolve(__dirname, "./.modernizrrc.js")
}
}
};
Expose Configuration
Make your config/webpack/environment.js look like this:
const { environment } = require("#rails/webpacker");
const customConfig = require('./custom');
environment.config.merge(customConfig);
module.exports = environment;
Import Modernizr
Add the following line to app/javascript/packs/application.js:
import modernizr from 'modernizr';
Load Your Pack
Add this to your layout:
<%= javascript_pack_tag "application", defer: true %>
Voila
Load up your site in a browser, inspect, and confirm that (a) modernizr CSS classes have been added to the DOM, and (b) you aren't seeing any webpack compilation errors in the console.
Further Reading
I came upon this question when I was looking to set up modernizr using webpacker in a Rails 5 app, saw the question was unanswered, and figured it out myself. If you want to know how all of this works, I suggest reading the docs for webpacker and webpack-modernizr-loader.

Related

After upgrading Angular, webpack module source-map-loader is throwing "this.getOptions is not a function"

I am currently building my angular project via webpack with source-map-loader to extract source maps, like so:
module.exports = {
// ...
module: {
rules: [
{
test: /\.js$/,
enforce: "pre",
use: ["source-map-loader"],
},
],
},
};
This works fine with my Angular 11 build.
Once I upgrade my angular packages to Angular 12, I begin to get the following error:
Module build failed (from ./node_modules/source-map-loader/dist/cjs.js):
TypeError: this.getOptions is not a function
at Object.loader (./node_modules/source-map-loader/dist/index.js:21:24)
Removing this section from my webpack module allows the build to succeed but I am no longer extracting the source maps, causing my bundle to increase in size.
I have tried upgrading source-map-loader to latest version and did not change the error.
I have dug into the node_module and it is complaining about this section of code:
async function loader(input, inputMap) {
const options = this.getOptions(_options.default);
I have seen may other questions on here in regards to sass-loader and other style loaders for Vue but this is for Angular and is mad about extracting source maps.
There are some breaking changes when going to Angular 12 but upgrading to webpack 5.0.0 did not seem to make a difference
What are some other things I can do to debug this?
By looking at the source code v1.1.3 we do see
import { getOptions } from "loader-utils";
But after v2.0 or even v3.0, this import was deleted.
It came from the library loader-utils
Since v2.0, package.json doesn't import it anymore.
Looks like it has been deprecated, getOptions should be use from Webpack type instead of loader-utils.
Maybe your error come from a conflict with an old dependencie from your node_modules, you should remove the old one from your directory and try again
rm -rf node_modules/#types/loader-utils
rm -rf node_modules/loader-utils

Module not found: Error: You attempted to import babel-preset which falls outside of the project src/ directory

I'm developing an application created using create-react-app
But then I needed to use mediainfojs library, this library requires wasm files, and based on what I understood I couldn't add it using create-react-app, I had to eject it.
After ejecting it, I went to mediainfo information on how to add the wasm on the webpack
They use the CopyPlugin, but then when I tried to do that it complained about the versions of my webpack (4) and the CopyPlugin.... so, I decided to migrate to webpack 5
That is when the pain starts... after follow their migration tutorial and do a bunch of modifications on my webpack.config I got to the following error while runing yarn build:
Module not found: Error: You attempted to import /MyWorkspace/project/node_modules/babel-preset-react-app/node_modules/#babel/runtime/helpers/esm/asyncToGenerator which falls outside of the project src/ directory. Relative imports outside of src/ are not supported.
The only place calling this babel-preset-react-app are in the configuation
Here:
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrc,
loader: require.resolve("babel-loader"),
options: {
customize: require.resolve(
"babel-preset-react-app/webpack-overrides"
),
And here:
{
test: /\.(js|mjs)$/,
exclude: /#babel(?:\/|\\{1,2})runtime/,
loader: require.resolve("babel-loader"),
options: {
babelrc: false,
configFile: false,
compact: false,
presets: [
[
require.resolve("babel-preset-react-app/dependencies"),
{ helpers: true },
],
],
cacheDirectory: true,
cacheCompression: isEnvProduction,
// If an error happens in a package, it's possible to be
// because it was compiled. Thus, we don't want the browser
// debugger to show the original code. Instead, the code
// being evaluated would be much more helpful.
sourceMaps: false,
},
},
I have looked into similar issues reported here, but mostly of them seem to be related to either static files being dynamically imported or imports referencing ".." dir after the project directory
The full webpack config file is here
I'm probably missing something very silly, I'd be glad if someone can point it out.
I had a similar challenge and I was able to fix this by adding these definitions at the top of my webpack.config file
const babelRuntimeEntry = require.resolve('babel-preset-react-app');
const babelRuntimeEntryHelpers = require.resolve(
'#babel/runtime/helpers/esm/assertThisInitialized',
{ paths: [babelRuntimeEntry] }
);
const babelRuntimeRegenerator = require.resolve('#babel/runtime/regenerator', {
paths: [babelRuntimeEntry]
});
Then where you have the ModuleScopePlugin in the resolve.plugins
update it to be
new ModuleScopePlugin(paths.appSrc, [
paths.appPackageJson,
babelRuntimeEntry,
babelRuntimeEntryHelpers,
babelRuntimeRegenerator])
I'm also attempting to upgrade an ejected CRA project to Webpack 5. I was able to move forward using babel-preset-react-app-webpack-5, only to encounter the next CRA-related issue.
Be sure to replace calls like require.resolve("babel-preset-react-app/dependencies") with require.resolve("babel-preset-react-app-webpack-5/dependencies").
Also, be aware the package does not appear to be production-ready, but my own project is still in early development.
I had this issue with a few other babel packages after trying to upgrade an ejected CRA app to webpack v5. I tried many different approaches some of which worked in dev but not in prod and vice versa. I found this comment in the storybook github and it was the only thing that that seemed to work in all scenarios for me.
It's kinda annoying, but by simply moving the offending packages from devDependencies in my package.json to dependencies, it seems to fix the issue. I could spend more time trying to figure out why that fixes it, but I'll leave that to someone with more free time. :)

Webpack 5 Receiving a Polyfill Error?!?! My JavaScript React project is receiving a polyfill error while trying to compile my webpack.config.js file

I am taking a course on Udemy (it is Brad Schiff's React for the Rest of Us course here) that is based on React and I am receiving an error related to webpack which is keeping it from compiling.
I am getting the following error as I am trying to compile my webpack file from a Udemy course I am taking... here is a picture of the error I am receiving on my terminal:
please view it here
Here is the text of the error but please view the link for more details as a screenshot nonetheless:
Module not found: Error: Can't resolve 'path' in '/Users/seanmodd/Development/2021/BradSchiff/Frontend/node_modules/webpack/lib/util'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
- install 'path-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "path": false }
# ./node_modules/webpack/lib/CleanPlugin.js 12:17-37
# ./node_modules/webpack/lib/index.js 115:9-33
# ./node_modules/dotenv-webpack/dist/index.js 12:15-33
# ./node_modules/dotenv-webpack/browser.js 1:13-38
# ./app/components/HomeGuest.js 5:15-40
# ./app/Main.js 8:0-47 38:96-105
Run npm install node-polyfill-webpack-plugin in your terminal`
go to your webpack.config.js and paste this:
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin')
module.exports = {
// Other rules like entry, output, devserver....,
plugins: [
new NodePolyfillPlugin()
]}
this should fix it, they removed automatic polyfills in webpack 5 that's why downgrading web3 version will fix it too
They have removed automatic polyfills in webpack 5. We have to include them ourselves.
More info here
By looking at the error stack, we see that ./app/components/HomeGuest.js line 15 requires the path module.
If you really need the path module on the client side, you have to add this in the webpack config file:
module.exports = {
// ... your config
resolve: {
fallback: {
path: require.resolve("path-browserify")
}
}
}
And also, install the path-browserify module (npm install path-browserify).
However, you may not need this module on the client side, and then the fix is to edit the HomeGuest.js file line 15 in such a way that the path module is not required.

Babel plugin transform-remove-console not working with Vue CLI 4 #vue/cli-plugin-babel/preset?

With a VueJS project created by Vue CLI 4, you get Babel configured with this handy preset in babel.config.js:
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset',
],
};
I'm trying to use babel-plugin-transform-remove-console to remove console.* from the built JS files.
Installed the plugin as a dev dependency by: npm i -D babel-plugin-transform-remove-console
Then modified babel.config.js:
module.exports = (api) => {
var env = api.cache(() => process.env.NODE_ENV);
var plugins = [];
// Change to 'production' when configs are working
if (env === 'development') {
plugins.push(['transform-remove-console', { exclude: ['error', 'warn'] }]);
}
return {
presets: ['#vue/cli-plugin-babel/preset'],
// plugins,
// Doesn't work even when always on?
plugins: ['transform-remove-console'],
};
};
This should work by running npm run serve -- --reset-cache, and I've also tried building the app many times with different environments, but the console loggings are still showing up in the browser's console?
Is Vue CLI's preset somehow mixing it up for not being able to set plugins via this configuration file?
UPDATE: Created a bug report to Vue CLI repo, and while creating a minimal bug reproduction repository, I found out this plugin is working with a new project.
However, I have no idea what is causing this as I've synced this application with the newest CLI bootstrapped template, and also tried nuking NPM cache by `npm cache clean --force.
I ran into the same problem. This did not work:
plugins: ['transform-remove-console']
But this worked:
plugins: [['transform-remove-console', { exclude: ['error', 'warn'] }]]
Hope this helps others who encounter the same issue.
It seems #Zydnar's suggestion of nuking node_modules folder may have helped, however, I also found out that my recent NPM packages upgrades had been interrupted and had not been fully successful. There was some Vue CLI plugins that had different versions.
After nuking node_modules and upgrading all the packages this Babel plugin started working!

webpack config for haml

So I've just started using webpack for my projects. I am using webpack to try and compile my haml templates to jsx to react elements. To do this I am using the haml-jsx and babel-loader loaders.
so, the problem I'm having right now arises when webpack goes to load the .haml template. I keep getting this error "module parse failed: unexpected token. you may need an appropriate loader to handle this file type". idk what is preventing the haml-jsx loader from working right, but as I said I'm new to webpack so idk if it's my webpack config file or something outside of that. That's why I'm coming to you folks!
the following is my webpack config file:
const path = require('path');
module.exports = {
entry:path.resolve(__dirname,"index.js"),
module:{
rules:[
{
test:/\.haml$/,
use:[
{
loader:"babel-loader",
options:{
presets: ['#babel/preset-env'],
plugins: [require('#babel/plugin-syntax-jsx')]
}
},
{
loader:"haml-jsx-loader"
}
]
},
]
},
output: {
filename:"bundle.js",
path: path.resolve(__dirname,"/distro")
},
};
also my directory structure looks like this
webpack
-sass(dir)
-distro(dir)
-haml(dir)
-tamplate.haml
-node_modules
-webpack.config.js
-babel.config.js
-index.js
-package.json
any suggestions at all would help! thanks!
The issue does not have anything to do with haml itself. The loaders are fine, except of the fact, that one of them can not parse - and therefore load - the given file.
Having a look at your babel-loader config, the fact that you're using React is the key to your issue. #babel/plugin-syntax-jsx is not what you're looking for. You should be using #babel/plugin-transform-react-jsx.
To be honest, the documentation for all the babel plugins is pretty bad actually.

Categories