How to use webpack with babel-loader and flow - javascript

I'm struggling with what I feel shouldn't be too hard of a setup.
I want these three technologies to work together:
webpack to bundle code
babel so that I'm able to write modern JavaScript
flow because type checking is helpful just like tests and linter
I've already gone trough several setups of this but none of the articles I've found on the web appears to be helpful.
I've defined 3 scripts in my package.json, run, flow and build.
Typechecking with yarn run flow works perfectly, and so does executing the script trough babel-node using yarn run start.
But when I execute yarn run build the following error appears trough webpack:
$ ./node_modules/webpack/bin/webpack.js
Hash: 207d42dac5784520fc99
Version: webpack 3.10.0
Time: 49ms
Asset Size Chunks Chunk Names
bundle.js 2.65 kB 0 [emitted] main
[0] ./src/main.js 181 bytes {0} [built] [failed] [1 error]
ERROR in ./src/main.js
Module parse failed: Unexpected token (3:5)
You may need an appropriate loader to handle this file type.
| // #flow
|
| type Foo = {
| foo: string,
| };
error Command failed with exit code 2.
It appears to me that the type annotations don't get removed correctly at the right point. Sadly this also happend if I specify the babel options in webpack directly as opposed to the .babelrc.
This currently defeats me in bundling up a bunch of .js files whilst using flow and while I found several plugins that supposedly strip flow annotations simply using the flow preset is what flowtype.org appears to recommend.
For reproducibillity, my project files look like this:
package.json:
{
…
"dependencies": {},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.3",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"babel-preset-flow": "^6.23.0",
"flow-bin": "^0.60.1",
"webpack": "^3.9.1"
},
"scripts": {
"build": "./node_modules/webpack/bin/webpack.js",
"start": "./node_modules/babel-cli/bin/babel-node.js src/main.js",
"flow": "./node_modules/flow-bin/cli.js"
}
}
.flowconfig:
[include]
./src
[ignore]
[libs]
[lints]
[options]
.babelrc:
{
"presets": ["env", "flow"]
}
webpack.config.js:
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/main.js',
output: {
path: __dirname,
filename: 'bundle.js',
},
resolve: {
modules: [
path.resolve('./src/'),
'node_modules',
],
extensions: ['.js'],
},
module: {
rules: [
{
test: '/.js$/',
loader: 'babel-loader',
},
],
},
};
src/main.js:
// #flow
type Foo = {
foo: string,
};
const defaultFoo: Foo = {
foo: 'bar',
};
console.log(defaultFoo);

Download the relevant presets and add them to the webpack.config.js as follows:
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015', 'stage-0', 'react']
}
}
}
]
}

Related

using gulp with webpack-stream and babel loader to convert jsx

I'm building a website in Wordpress and I am trying to use gulp, webpack-stream, and babel-loader to convert JSX to JS (I was successful at using gulp to sass my CSS, so I removed that code).
Whenever I run the gulp command in terminal to convert the JSX, I get this incorrect output in the generated Javascript file:
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);n(1);console.log("ugh")},function(e,t){console.log("test running")}]);
I can't figure out if I'm getting this error because I'm missing vital packages or if something else is wrong with my gulp commands.
Here is my package.json's dependencies
{
"devDependencies": {
"#babel/core": "^7.11.4",
"#babel/preset-env": "^7.11.0",
"#babel/register": "^7.10.5",
"#wordpress/browserslist-config": "^2.7.0",
"autoprefixer": "^9.8.6",
"babel-loader": "^8.1.0",
"babelify": "^10.0.0",
"browserify": "^17.0.0",
"browserslist": "^4.14.0",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-postcss": "^8.0.0",
"gulp-sass": "^4.1.0",
"gulp-sourcemaps": "^2.6.5",
"gulp-terser": "^1.4.0",
"webpack-stream": "^6.1.0"
},
"browserslist": [
"extends #wordpress/browserslist-config"
]
}
Here is my gulpfile.babel.js file:
// load gulp
import gulp from 'gulp';
// utility
import sourcemaps from 'gulp-sourcemaps';
// css-related
import sass from 'gulp-sass';
import postcss from 'gulp-postcss';
import autoprefixer from 'autoprefixer';
// js-related
import webpack from 'webpack-stream';
// project
const paths = {
scripts: {
src: 'src/scripts/bundle.js',
dest: './build/js/'
}
}
// enable javasript
export const scripts = (done) => {
return gulp.src( paths.scripts.src )
.pipe( webpack({
// module: {
// rules: [
// {
// test: /\.js$/,
// use: {
// loader: 'babel-loader',
// options: {
// presets: ['#babel/preset-env']
// }
// }
// }
// ]
// },
output: {
filename: 'bundle.js'
}
}) )
.pipe( gulp.dest( paths.scripts.dest ) );
done();
}
I commented out the webpack module items because I was eliminating the possible reasons for why it wasn't working. When I commented out webpack, the code "worked" in that it copied the file over to the build folder.
Here is the bundle.js file that contains JSX
console.log('ugh');
import './components/test';
let x = 0;
and here is what test.js contains
console.log("test running");
I also received the following message inside terminal:
(node:13196) [DEP0097] DeprecationWarning: Using a domain property in MakeCallback is deprecated. Use the async_context variant of MakeCallback or the AsyncResource class instead.
[22:53:54] Version: webpack 4.44.2
Built at: 10/20/2020 10:53:54 PM
Asset Size Chunks Chunk Names
bundle.js 1020 bytes 0 [emitted] main
Entrypoint main = bundle.js
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
[22:53:54] Finished 'scripts' after 1.69 s
I'm totally new to using node, npm, and gulp, and have been following tutorials as best I can to try to get this to work, but every tutorial is either old, or I end up with garbage code in the destination file. I'm also the lone developer and designer, and I desperately need some feedback/assistance. I would be forever grateful to whoever can help me get this to work properly, and am happy to provide any additional information in order to figure this out.

External React component library JSX Babel wont compile

I'm trying to extract certain compoennts in my React Application to a separate reusable component library.
What I've done, is cloned this project: https://rinsejs.io/ and subsequently referenced the github repo in my main projects package.json
entry in package json of core project
"react-sharedlib": "git+ssh://git#github.com/myrepos/react-sharedlib.git#master",
Webpack.config inside react-sharedlib
// Path is in Node for free and will make simple resolving of directories no
// matter which part of your file system your library lives in
const path = require('path');
// Webpack is just a bunch of keys on module.exports!
module.exports = {
// This is where our app starts. This is why we hnpm install --save-dev babel-core#6.4.5ave done all this importing
// and exporting, to get to here
entry: './src/index.js',
// module (I know it's a bit weird to hanpm install --snpm install --save-dev babel-preset-es2015#6.3.13ave-dev babel-loader#6.2.1ve module.exports.module) is where we
// define all the rules for how webpack will deal with thing.
module: {
// rules takes an array, each item containing the respective rules
rules: [
{
// First up, our JavaScript rules.
// If you want to use the .jsx extension, you can change this line to
// test: /\.jsx?$/,
// The ? in the regex just means "optional"
test: /\.js$/,
// Don't bother spending time transpiling your installed packages
// exclude: /node_modules/,
// This is where we tell webpack to use babel to transpile our JS.
// The configuration can go here, but in this case it's in ./babelrc.js
use: {
loader: 'babel-loader',
},
},
{
// I haven't used SCSS in the base example, but it's here for you if you
// want! If you want to use CSS, you can change this next like's regex to
// /\.(css|scss)$/ or even just /\.css$/
test: /\.scss$/,
use: [
// These three libraries are commonly used together to turn Sass into
// CSS, then be able to load the CSS directly with imports. From there
// It gets put in the DOM for you.
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'sass-loader' },
],
},
{
// Some image formats so you can import images
test: /\.(png|gif|jpg|svg)$/,
use: {
loader: 'url-loader',
options: {
limit: 50000,
},
},
},
],
},
// Here we define explicitly the file types we intend to deal with
resolve: {
extensions: ['.scss', '.js', '.json', '.png', '.gif', '.jpg', '.svg'],
},
// This is where we define how everything gets output.
// dist is a common output folder, and it should be gitignored. The build can
// be run after publishing so you don't wind up with it in source control
output: {
path: path.resolve(__dirname, 'dist/'),
publicPath: '',
// You can do fun things here like use the [hash] keyword to generate unique
// filenames, but for this purpose rinse.js is fine. This file and path will
// be what you put in package.json's "main" field
filename: 'rinse.js',
// This field determines how things are importable when installed from other
// sources. UMD may not be correct now and there is an open issue to fix this,
// but until then, more reading can be found here:
// https://webpack.js.org/configuration/output/#output-librarytarget
libraryTarget: 'umd',
},
};
Babel config inside shared-lib:
{
"presets": ["#babel/env", "#babel/preset-react", "es2015", "react"],
"plugins": ["#babel/plugin-syntax-dynamic-import"]
}
Package.JSON inside shared-lib:
{
"name": "react-sharedlib",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"dependencies": {
"#babel/preset-react": "^7.0.0",
"babel-core": "^6.4.5",
"babel-loader": "^6.2.1",
"babel-preset-es2015": "^6.3.13"
},
"devDependencies": {
"#babel/plugin-syntax-dynamic-import": "^7.2.0",
"babel-preset-react": "^6.3.13"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/myrepos/react-sharedlib.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/myrepos/react-sharedlib/issues"
},
"homepage": "https://github.com/myrepos/react-sharedlib#readme"
}
When I try to build my project I get this error. (Which looks like a problem with babel in some capacity, not being able to reference the JSX syntax or needing a loader configured. Anyone any idea what I'm doing wrong here, or what other things to try? As you can see from my dependencies I've had a go at installing Babel loaders, but to no avail. I assume I may just be missing a piece of configuration somewhere to get it to recognise the HTML inside the JS file.
ERROR in /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/components/Button/Button.js 23:8
Module parse failed: Unexpected token (23:8)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| // along without changing any of the contents. This is basically just creating
| // a copy to pass along
> return <ButtonWrapper {...props}>{props.children}</ButtonWrapper>;
| }
|
# /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/components/Button/index.js 2:0-30 4:15-21
# /Users/moi/git/usersection/user-section/node_modules/react-sharedlib/src/index.js
# ./app/App.js
# ./index.js
Latest version of React btw.
Webpack 4.29.6
Update: **
Following on from the answer posted below, my shared library webpack.config.js file now contains this entry which unfortunately made no difference.
rules: [
{
// First up, our JavaScript rules.
// If you want to use the .jsx extension, you can change this line to
// test: /\.jsx?$/,
// The ? in the regex just means "optional"
test: /\.js$/,
// Don't bother spending time transpiling your installed packages
// exclude: /node_modules/,
// This is where we tell webpack to use babel to transpile our JS.
// The configuration can go here, but in this case it's in ./babelrc.js
use: {
loader: 'babel-loader',
options: {
babelrcRoots: [".", "node_modules/react-sharedlib"]
}
},
}
CORE PROJECT .babelrc:
{
"presets": ["#babel/env", "#babel/preset-react"],
"plugins": ["#babel/plugin-syntax-dynamic-import"]
}
SHARED PROJECT .babelrc:
{
"presets": ["#babel/env", "#babel/preset-react", "es2015", "react"],
"plugins": ["#babel/plugin-syntax-dynamic-import"]
}
By default, Babel assumes that .babelrc files in node_modules are ignored, because they were probably published on accident, and usually they reference plugins and presets that are in their devDependencies and thus probably aren't installed. The config could even be for a different version of Babel, so even if they were all installed, they still might not work.
This means you need to either:
Tell Babel explicitly that node_modules/react-sharedlib is safe to load the config for.
Configure your application's Babel config to compile that specific node_modules/react-sharedlib.
The first can be accomplished by specifying:
babelrcRoots: [".", "node_modules/react-sharedlib"],
in babel-loader's options.
The second would require using a babel.config.js config file in your application, and exporting your project-wide plugins there, so that they apply to any file you pass to Babel.
The Babel docs for config files are also a good place to review.

Unable to load stage-3 javascript file using babel-loader from webpack

Overview
Following the Auth0 documentation, they have a JavaScript file that has field variables (stage-3). When running my app, I get the following error:
ERROR in ./src/auth/AuthService.js
Module parse failed: Unexpected token (7:16)
You may need an appropriate loader to handle this file type.
|
| export default class AuthService {
| authenticated = this.isAuthenticated();
| authNotifier = new EventEmitter();
|
Above, the unexpected token is the first = sign after authenticated.
Diagnosing the Error
Downloading and running the sample project from Auth0's Github works successfully.
Running the following command using babel-cli parses the file successfully:
$ node node_modules\babel-cli\bin\babel.js src\auth\AuthService.js --presets stage-3
It is only when I run the application that the error is thrown, so I suspect there's something fishy in the webpack config.
My Configuration
The following is my .babelrc config:
{
"presets": [
["env", { "modules": false }],
"stage-3"
],
"plugins": ["transform-runtime"]
}
I've only included the relevant parts of my webpack config, but can provide the full file if necessary:
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader',
include: [path.join(__dirname, '..', 'src')],
},
// ...
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json'],
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}
// ...
Dependencies Info
The following are the babel/webpack dependency versions in my project:
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.2",
"babel-loader": "^7.1.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"webpack": "^3.6.0",
With All That Said
How can I further figure out what is causing the error to be thrown? It's pretty specific, but it's clear that babel can process the file just fine using the babel-cli. After spending many hours researching this issue, trying different options in the webpack config, using .babelrc and forcing webpack to not use it, using stage-2 instead of stage-3, I feel like I've tried everything.
My configuration isn't much different than the one in Auth0's sample project. Copying and pasting their .babelrc file into mine as well as their js webpack rules didn't seem to have an effect either; I just can't get it to work with my project.
I've found that most people that have had webpack problems (after ruling out the loader issue) have the issue because there is something incorrect setup in your webpack config.
For my webpack config, I needed to change this:
module: {
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader',
include: [path.join(__dirname, '..', 'src')],
},
// ...
]
},
to this:
module: {
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
// ...
]
},
Because my webpack.config.js file existed under src, so the issue might've been that the .. argument in my include property wasn't pointing to the right folder to look for .js files in.
I needed to exclude node_modules because it would otherwise try to parse files in that directory.

Node JS Webpack Babel with async

When trying to compile my server-side code, I get the following error:
Module parse failed: (...babel-loader-path)?{"presets":["es2015-node4","es2015"]} (...) Unexpected token (86:6)
You may need an appropriate loader to handle this file type.
This error seems to be caused by an Async function that I am trying to import. Do I need to change my webpack configuration?
My webpack config file:
const webpack = require('webpack');
module.exports = {
target: 'node',
entry: ['./server/index.js', './node_modules/webpack/hot/poll?1000'],
output: {
path: './dist',
filename: 'server.bundle.js',
libraryTarget: 'commonjs',
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
externals: [/^[a-z]/],
module: {
loaders: [{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015-node4', 'es2015'],
},
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015-node4', 'es2015'],
},
}
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
],
devtool: 'source-map',
};
If you are using Webpack to compile your Node code, then that is not a good approach. You should simply use babel-node which is an amazing way to transpile your node code.
For that in your package.json do the following
"scripts": {
"dev": "node_modules/.bin/nodemon --exec babel-node server/index.js",
"prestart": "node_modules/.bin/babel server --out-dir dist",
"start": "node dist/index.js"
},
"devDependencies": {
"#babel/cli": "^7.0.0-beta.40",
"#babel/core": "^7.0.0-beta.40",
"#babel/node": "^7.0.0-beta.40",
"#babel/preset-env": "^7.0.0-beta.40",
"#babel/preset-stage-2": "^7.0.0-beta.40",
"nodemon": "^1.11.0"
}
In your .babelrc file, do the following.
{
"presets": [
"#babel/preset-env",
"#babel/preset-stage-2"
]
}
Then in your project directory create a folder called server and in that folder create a file called index.js which creates your node http server.
For a reference have a look at Babel-Node Documentation
Or have a look at this amazing small tutorial kind of example created by the awesome folks at Babel Example Node Server Using Babel-Node
P.S: In the package.json file the npm run dev watches your code and npm start commands compiles your code ready to be shipped for production.
There seems to be a mis-understanding with regard to the babel preset usage. The preset you want is not the target version of javascript you want to output. For that you need to set target appropriately. Instead you needed the preset that corresponds to the version of javascript you are writing in. The presets are collections of transformers that instruct babel how to deal with specific javascript constructs.
In babel <=6 you need either: es2017 or transform-async-to-generator presets to use the async keyword. After babel 7 the recommendation is to use:
{
"presets": ["#babel/preset-env"]
}
This allows babel to support all modern java-script syntax's that have been finalized. It will then transpile to whatever syntax your target setting indicates. I personally would use a browserslist query in package.json for this so other tools like postcss automatically pick up the same target information.

How to fix the webpack bug: "you may need an appropriate loader to handle this file type." when I useing webpack to load css files

I am leaning webpack. However, here comes a bug that "You may need an appropriate loader to handle this file type.", I have checked the webpack.config.js, it is correct.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require("webpack");
module.exports = {
entry: {
app: './src/main.js',
print: './src/print.js'
},
devtool: 'inline-source-map',
devServer: {
contentBase: 'dist',
hot: true,
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Output Management'
}),
new webpack.HotModuleReplacementPlugin()
]
};
Additionally, here is my js file and css file:
import './style.css';
body {
background-color: blue;
}
And the console log this:
./src/style.css
Module parse failed: D:\FrontEndWorkSpace\webpack-demo\src\style.css Unexpected token (1:5)
You may need an appropriate loader to handle this file type.
| body {
| background-color: blue;
| }
Additional, I have already installed both style-loader and css-loader, here are my dependencies on my package.json:
"devDependencies": {
"clean-webpack-plugin": "^0.1.16",
"css-loader": "^0.28.4",
"csv-loader": "^2.1.1",
"file-loader": "^0.11.2",
"html-webpack-plugin": "^2.29.0",
"style-loader": "^0.18.2",
"webpack": "^3.4.1",
"webpack-dev-server": "^2.6.1",
"xml-loader": "^1.2.1"
}
EDIT: For some unknown reasons, it's works.
Make sure you have installed the loaders you're trying to use from NPM. You should see them in both your package.json file and in your node_modules folder of the project. If you don't see them, you can install them and save them to your dev dependencies in your terminal:
$ npm install style-loader css-loader --save-dev
Last bit, I've found this YouTube video series extremely helpful in getting started with Webpack 2. It's changed a lot in its first couple of years, so relevant references are tricky to separate from the obsolete ones.
Good luck taming the webpack beast!
EDIT: Removed extra stuff.

Categories

Resources