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.
Related
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. :)
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.
I'm trying to use this package in my application.
It appears to be written in ES6 so I need a transpiler like babel. I've started a new project and tried the following:
Create new index .html / .js file for testing.
npm install audio-effects
npm install gulp gulp-babel babel-preset-es2015
Create .babelrc
After trying to run this from the dist folder with python -m SimpleHTTPServer, I got an error: index.js:3 Uncaught ReferenceError: require is not defined.
After some digging, this is because require can't be used client-side. So next I looked into using WebPack to allow me to use require.
I went into my dist folder (where my transpiled javascript is) and ran:
webpack ./index.js index.js
But now I'm getting the error index.js:78 Uncaught SyntaxError: Unexpected token import.
Can anybody see what I'm missing (apart from a NPM-ES6-Gulp-WebPack tutorial)? I seem to be stuck in a loop of WebPack-ing and transpiling.
index.html
<!DOCTYPE html>
<html>
<body>
<h4>Welcome</h4>
<button onclick="startAudio()">Start Audio</button>
<script src="js/index.js"></script>
<script type="text/javascript" src="bundle.js" charset="utf-8"></script>
</body>
</html>
index.js (pre-babel / WebPack - ification)
import {HasAudioContext} from 'audio-effects';
function startAudio() {
console.log("Start Audio...");
let audioContext = null;
if (HasAudioContext) {
console.log("Has Audio CTX");
audioContext = new AudioContext();
}
else {
console.log("No Audio CTX");
}
}
gulpfile.js
var gulp = require("gulp");
var babel = require("gulp-babel");
gulp.task("default", function () {
return gulp.src("src/app.js")
.pipe(babel())
.pipe(gulp.dest("dist"));
});
I've made some changes to the library (I'm the original author of the package). When installing the package with npm, you will now get the transpiled ES5 code instead of the ES6 source. You'll still need webpack, browserify, ... to load the module though.
This might fix the the Uncaught SyntaxError: Unexpected token import error, so please update your audio-effects library to the latest version.
The wrong imports as mentioned in the answer by Jorawar Singh should be resolved as well.
I'm still working on the library so if you run into any problems, feel free to create an issue or pull request on github.
I personally use the package with webpack. this is my webpack.config.babel.js file (remove comments).
Note: I'm using react, if you don't set the react parameter to false.
import config from 'madewithlove-webpack-config';
export default config({
react: true,
sourcePath: 'src', // Source directory
outputPath: 'builds', // Transpiled coded directory
});
This imports a basic webpack config from https://github.com/madewithlove/webpack-config/
Since I'm writing code in ES6, I'm transpiling it with babel, my .babelrc file looks like this:
{
"presets": ["es2015", "stage-0"],
}
With all this setup, you can just run webpack with webpack-dev-server --inline --hot.
You don't have to use the madewitlove webpack config but it takes care of some standard setup like compiling scss etc.
I hope this gives you an insight in how to use the audio-effects package or any other ES6 package.
Well what i understand there was some issues with this library it was written es6 and when you do import and want to complie into es5 with webpack then webpack will also bummbel all the require modules for you. Here's my webpack.config look likes
var webpack = require('webpack');
var config = {
entry: './index.js',
output: {
path: __dirname + '/dist',
filename: 'bundle.js'
},
module: {
loaders: [ {
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}]
}
};
module.exports = config;
running by webpack will compile the library and your index.js file to bundle.js
there was some other issues i think in order to get this library you need to do some small changes in library.
from
'./Helpers/HasAudioContext'; //this doesn't exist and
//webpack will give you compile error
to
'./helpers/hasAudioContext';
I had one issue whitch i couldn't resolve is i couldn't run the startAudio function but through the index.js i could (weard let me know if you find why)
in your index.js
document.getElementById("btn").addEventListener("click", startAudio);
there are still some issues witch i want to resolve and also there are some issues with the library witch need to be resolved
I have a TypeScript project which I am bundling with Webpack. It is a demo/docs app for an open source lib I am writing, so I want to show some of the source code as part of the docs.
In my webpack config I have:
loaders: [
{ test: /\.ts$/, loader: 'ts'},
{ test: /\.css$/, loader: 'style!raw' },
{ test: /\.html/, loader: 'html' }
]
which works fine for transpiling and bundling my TypeScript files. In one of my app components I do this:
basicCodeT: string = require('./basic-example-cmp.html');
basicCodeC: string = require('!raw!./basic-example-cmp.ts');
to load the source code into a string which I then want to display in the docs.
As you can see, there is a leading ! in the second line which I discovered seems to "bypass" the default loaders from the config and loads the raw TypeScript as a string.
In my dev build this works, but when I do a "production" build with the UglifyJsPlugin and OccurrenceOrderPlugin, I get the following output:
ERROR in ./demo/src/basic-example-cmp.html
Module build failed:
# ./demo/src/demo-app.ts 24:26-61
which corresponds to the line in the source where I try to require the raw TypeScript.
So, I want to pass basic-example-cmp.ts through the TS compiler as part of the app build, but also want to require it as raw text in the app.
My question then is: Is there a proper way to tell webpack to "ignore" loaders in specific require cases?
Is my way of prepending a ! correct? Is it a hack?
Update
Turns out my problem is simply due to the way Webpack handles HTML templates - it does not like the Angular 2 template syntax, see: https://github.com/webpack/webpack/issues/992
You can add two exclamation to ignore loaders in the webpack config file
!!raw!file.ts
one exclamation will only disable preloaders!
https://webpack.js.org/concepts/loaders/#inline
As far as I know that is the only way you are going to be able to load a file in two different ways. I expect the issue is that your paths are different in your production build.
I would suggest running webpack with the --display-error-details flag to get more info on why it fails.
Is there a proper way to tell webpack to "ignore" loaders in specific require cases?
Yes. Update your test in { test: /\.ts$/, loader: 'ts'}, as desired.
I have a React application with Components written in ES6 - transpiled via Babel and Webpack.
In some places I would like to include specific CSS files with specific Components, as suggested in react webpack cookbook
However, if in any Component file I require a static CSS asset, eg:
import '../assets/css/style.css';
Then the compilation fails with an error:
SyntaxError: <PROJECT>/assets/css/style.css: Unexpected character '#' (3:0)
at Parser.pp.raise (<PROJECT>\node_modules\babel-core\lib\acorn\src\location.js:73:13)
at Parser.pp.getTokenFromCode (<PROJECT>\node_modules\babel-core\lib\acorn\src\tokenize.js:423:8)
at Parser.pp.readToken (<PROJECT>\node_modules\babel-core\lib\acorn\src\tokenize.js:106:15)
at Parser.<anonymous> (<PROJECT>\node_modules\babel-core\node_modules\acorn-jsx\inject.js:650:22)
at Parser.readToken (<PROJECT>\node_modules\babel-core\lib\acorn\plugins\flow.js:694:22)
at Parser.pp.nextToken (<PROJECT>\node_modules\babel-core\lib\acorn\src\tokenize.js:98:71)
at Object.parse (<PROJECT>\node_modules\babel-core\lib\acorn\src\index.js:105:5)
at exports.default (<PROJECT>\node_modules\babel-core\lib\babel\helpers\parse.js:47:19)
at File.parse (<PROJECT>\node_modules\babel-core\lib\babel\transformation\file\index.js:529:46)
at File.addCode (<PROJECT>\node_modules\babel-core\lib\babel\transformation\file\index.js:611:24)
It seems that if I try and require a CSS file in a Component file, then the Babel loader will interpret that as another source and try to transpile the CSS into Javascript.
Is this expected? Is there a way to achieve this - allowing transpiled files to explicitly reference static assets that are not to be transpiled?
I have specified loaders for both .js/jsx and CSS assets as follows:
module: {
loaders: [
{ test: /\.css$/, loader: "style-loader!css-loader" },
{ test: /\.(js|jsx)$/, exclude: /node_modules/, loader: 'babel'}
]
}
View the full webpack config file
FULL DETAILS BELOW:
webpack.common.js - A base webpack config I use, so I can share properties between dev and production.
Gruntfile.js - Gruntfile used for development. As you can see it requires the webpack config above and adds some development properties to it. Could this be causing the problem?
Html.jsx - My HTML jsx component that tries to import/require the CSS. This is an isomorphic app (using Fluxbile), hence needing to have the actual HTML as a rendered component. Using the require statement seen in this file, in any part of my application, gives the error described.
It seems to be something to do with grunt. If I just compile with webpack --config webpack.common.js then I get no errors.
Short answer: It's a node runtime error. Trying to load CSS on the server in isomorphic apps is not a good idea.
You can't require css in the component that you are rendering on the server. One way to deal with it is to check if it's a browser before requiring css.
if (process.env.BROWSER) {
require("./style.css");
}
In order to make it possible you should set process.env.BROWSER to false (or delete it) on the server
server.js
delete process.env.BROWSER;
...
// other server stuff
and set it to true for the browser. You do it with webpack's DefinePlugin in the config -
webpack.config.js
plugins: [
...
new webpack.DefinePlugin({
"process.env": {
BROWSER: JSON.stringify(true)
}
})
]
You can see this in action in gpbl's Isomorphic500 app.
If you're building an isomorphic app with ES6 and want to include CSS when rendering on the server (important so basic styles can be sent down to the client in the first HTTP response) check out the #withStyles ES7 decorator used in React Starter Kit.
This little beauty helps ensure users see your content with styles when the page is first rendered. Here's an example isomorphic app I'm building leveraging this technique. Just search the codebase for #withStyles to see how it's used. It goes a little something like this:
import React, { Component, PropTypes } from 'react';
import styles from './ScheduleList.css';
import withStyles from '../../decorators/withStyles';
#withStyles(styles)
class ScheduleList extends Component {
We had a similar problem with our isomorphic app (and a lot of other problems, you can find details here). As for the problem with CSS import, at first, we were using process.env.BROWSER. Later we've switched to babel-plugin-transform-require-ignore. It works perfectly with babel6.
All you need is to have the following section in your .babelrc
"env": {
"node": {
"plugins": [
[
"babel-plugin-transform-require-ignore", { "extensions": [".less", ".css"] }
]
]
}
}
After that run your app with BABEL_ENV='node'. Like that:
BABEL_ENV='node' node app.js.
Here is an example of how a production config can look like.
You can also try this
https://github.com/halt-hammerzeit/webpack-isomorphic-tools
or this
https://github.com/halt-hammerzeit/webpack-react-redux-isomorphic-render-example
I used this babel plugin with success to solve a similar issue with less, svg and images. But it should work with any non js assets.
It rewrites all assets imports into variables, so as long as you run the compiled code just on the server and have a bundle built with webpack for the client, it should be fine.
The only drawback is that it onlyworks with named imports, so you'll have to:
import styles from './styles.css';
in order to make it work.
Make sure you are using the loaders in your webpack config:
module: {
loaders: [
{ test: /\.jsx$/, exclude: /node_modules/, loader: "babel" },
{ test: /\.css$/, loader: "style!css" }
]
}
You probably have an error in your Webpack config where you're using the babel-loader for all files, and not just .js files. You want to use a css loader for .css files.
But you shouldn't use import for loading any other module than Javascript modules, because once imports are implemented in browsers, you will only be able to import Javascript files. Use require instead in cases where you need Webpack specific functionality.
ORIGINAL POST
Webpack uses require and Babel lets you use import from ES6 which mostly do the same thing (and Babel transpiles the import to a require statement), but they are not interchangable. Webpacks require function lets you specify more than just a module name, it lets you specify loaders as well, which you cannot do with ES6 imports. So if you want to load a CSS file, you should use require instead of import.
The reason is that Babel is just a transpiler for what's coming in ES6, and ES6 will not allow you to import CSS files. So Babel won't allow you to do that either.
I've finally realised that this error is not originating at the compile stage, but rather at runtime. Because this is an ismorphic app, the components and any dependencies they have will first be parsed on the server (ie, in node). It is this that is causing the error.
Thanks for all the suggestions, I will post more if/when I figure out how to have per-component stylesheets in an isomorphic application.
I also met the same problem when I want to do the server-side render.
So I write a postcss plugin, postcss-hash-classname.
You don't require css directly.
You require your css classname js file.
Because all you require is js file, you can do the server-side render as usual.
Besides, this plugin also use your classname and file path to generate unique hash to solve css scope problem.
You can try it!
Solved With This...
https://github.com/michalkvasnicak/babel-plugin-css-modules-transform
$ npm install --save-dev babel-plugin-css-modules-transform
Include plugin in .babelrc
{
"plugins": ["css-modules-transform"]
}
And Import Css..... Like This Anywhere You Want
const styles = require('./test.css');
OR
import css from './styles.css'
Also See This... Apart From Css Files........................................................ .
https://www.npmjs.com/package/babel-plugin-transform-assets