Odd error when adding target: 'es5' to webpack.config.js file - javascript

I have been trying to learn full stack web development and began learning webpack and babel. I was starting very slow, I haven't even added any non development dependencies like react or electron yet. I am just attempting to understand the basics of how babel and webpack operate when used in conjunction. I have gotten my webpack file and it worked perfectly fine before I added the target: "es5", line. It now looks like:
module.exports = {
entry: './src/index.js',
target: "es5",
module: {
rules: [{
test: /\.js$/,
use: {
loader: 'babel-loader'
}
}]
}
}
which worked perfectly fine when it was converting the files to es5, but the webpack syntax used newer versions. When attempting to make webpack convert its own syntax to es5 - via the target: "es5", line - by running the command npx webpack --config webpack.config.js --mode=development it gives me the following error.
Error: For the selected environment is no default script chunk format available:
JSONP Array push can be chosen when 'document' or 'importScripts' is available.
CommonJs exports can be chosen when 'require' or node builtins are available.
Select an appropriate 'target' to allow selecting one by default, or specify the 'output.chunkFormat' directly.
Why am I getting this error and how is it remedied?
I should also note that I do have a separate file called babel.config.js that includes the following.
module.exports = {
presets: ["#babel/preset-env"]
}

Related

Confusing behavior when wiring together Rollup, ES modules, TypeScript, and JSX

The things I noted in the title - I started to learn them just recently. They are going not that smooth, so I have to ask this little question on StackOverflow.
What I require
Something to pack my stuff - here comes Rollup
Bare module imports for my own module files - using #rollup/plugin-node-resolve for this
Funny typed language - TypeScript and #rollup/plugin-typescript
React with JSX - it is react and react-dom packages, and typescript, which is able to process JSX
I read these docs to wire these tools together:
https://www.typescriptlang.org/tsconfig
https://www.npmjs.com/package/#rollup/plugin-typescript
I successfully used Rollup, #rollup/plugin-node-resolve, and TypeScript. But with addition of React things went odd.
Demo project
Please look at the example project I made for illustration:
https://github.com/Ser5/RollupWireBug
git clone https://github.com/Ser5/RollupWireBug.git
cd RollupWireBug/
npm install or yarn install
npm run build
The project structure is:
/
src/
js/ - only folder that contains my code
main.tsx - entry point
test-class.js - for testing bare import
buggy.tsx - should be excluded from building
dist/
bundle.js - Rollup output file
rollup.config.js
To my understanding the config should work like that:
resolve({
moduleDirectories: ['node_modules/', 'src/js/'],
extensions: ['.js', '.ts', '.jsx', '.tsx'],
}),
^ This should mean to bare import modules from node_modules/ and src/js/, searching for files with noted extensions.
And here comes the puzzling part:
typescript({
include: [
'./**/*',
//'src/js/**/*',
//"node_modules/**/*",
],
exclude: [
"node_modules/",
"dist/",
"src/buggy.tsx",
],
}),
^ This is how a configuration works for me. I must write ./**/* in the include - which seems odd for me, as I believe I don't need to include every file from the project root - I need only src/js/.
If instead of ./**/* I use src/js/**/*, or src/js/**/* with node_modules/**/* - Rollup refuses to build the project, screeching:
src/js/main.tsx → dist/bundle.js...
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src\js\main.tsx (7:13)
5:
6: let myName = 'Ser5';
7: let s = <h1>{myName}</h1>;
^
8: console.log(s);
Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
It doesn't recognize the JSX syntax.
Because of ./**/* in the include I also need to have the exclude section - otherwise Rollup/TypeScript will crawl into src/buggy.js and even dist/, and try to build them as well.
tsconfig.json
I understand it as follows:
"baseUrl": "./",
"paths": {
"*": [
"node_modules/*",
"src/js/*",
],
},
^ "Go search modules in node_modules/ and src/js/ directories."
"outDir": "tsout",
^ Really no idea WTF is this. Looks like some temporary folder.
And if instead of this part in rollup.config.js
typescript({
include: [
'./**/*',
],
...
}),
I write the same thing in tsconfig.json
{
include: [
'./**/*',
],
"compilerOptions": {
...
The project still doesn't build - displaying Error: Unexpected token for JSX syntax.
Questions
Where am I wrong?
Why for #rollup/plugin-typescript I have to include ./**/* right from the root, and block some files with include section? Why can't I simply write src/js/**/* ?
Why include works only for #rollup/plugin-typescript? And I can't write that include in tsconfig.json?
Will try to give you some hints:
outDir option says where the JavaScript files will be generated
#rollup/plugin-typescript will load any compilerOptions from the tsconfig.json file by default. So if you are passing any option to that (like you did in your repo) it will override those ones that you set in tsconfig.json. Might be better to decide where to config stuff for TS
Specifically for your error. See docs here.
You have to do this basically:
import jsx from 'acorn-jsx';
import typescript from '#rollup/plugin-typescript';
export default {
// … other options …
acornInjectPlugins: [jsx()],
plugins: [typescript({ jsx: 'preserve' })]
};
Check Vite out by the way if you want to avoid all this config shenanigans! :)

webpack load AMD modules without bundling

I'm migrating a web app from requireJS to webpack.
With requireJS, I have different configurations depending on the environment.
For live environment I use r.js to minify and bundle all of my
modules and their dependencies into a single file. Afterwards, I add
almondJS to manage the dependencies and then I load my js bundle like the following:
<script src="bundle.min.js"></script>
For my development environment, I Load requireJS like this:
<script src="require.js" data-main="/main-config"></script>
and requireJS will use my configuration file specified by data-main, to load modules and their
dependencies asynchronously
As you can see, with requireJS module loading and bundling are two separate processes and that allows me to debug AMD modules during development without needing sourcemaps
How can I achieve this scenario using webpack as a module loader only without bundling during development ?
If this is not possible, is there any other way I can see my source files in the browser debugger without generating sourcemaps?
How can I achieve this scenario using webpack as a module loader only without bundling during development ?
Webpack will always bundle, despite the envieronment.
If this is not possible, is there any other way I can see my source files in the browser debugger without generating sourcemaps?
If your code is transpiled/compiled, you'll need sourcemaps to see that. There is no way to workaround that.
It's true that if your code is transpiled then you'll need sourcemaps. But it is possible to get around bundling though. Yes, webpack will really always try to bundle, but with plugins the code can be taken out of the bundle and placed in the output directory as if it was simply run through the transpiler.
I have a node application that I want to simply transpile to ES5 file-by-file and not bundle anything. So my config to do that is roughly this:
let config = {
entry: [
glob.sync(srcDir + '/**/*.js') // get all .js files from the source dir
],
output : {
filename : '[name].rem.js', // webpack wants to bundle - it can bundle here ;)
path: outDir
},
resolve: {
alias: {
'app': appDir
}
},
plugins: [
new RemoveEmptyScriptsPlugin({extensions: ['js'], scriptExtensions: /\.rem\.js/}) // for all .js source files that get bundled remove the bundle .rem.js file
],
module: {
rules:[{
test: /\.jsx?$/,
type: 'asset/resource', // get webpack to take it out instead of bundling
generator: {
filename: ({filename}) => filename // return full file name so directory structure is preserved
},
use: {
loader: 'babel-loader',
options: {
targets: { node: 16 },
presets: [
['#babel/preset-env', { modules: 'commonjs' /* transpile import/export */}],
]
}
}
}]
}
};
// Since the code does not go through the full pipeline and imports are not getting resolved, aliases will remain in the code.
// To resolve them it takes to hack the aliases object into the babel config
config.module.rules[0].use.options.plugins.push(['babel-plugin-webpack-alias-7', {config: {resolve: {alias: config.resolve.alias}}}];
But then it appeared that the currently published babel-plugin-webpack-alias-7 does not support providing an Object to the config option so I had to patch the plugin https://github.com/shortminds/babel-plugin-webpack-alias-7/pull/22
Ah, and then the webpack-remove-empty-scripts plugin had an issue with my idea so I had to patch that too https://github.com/webdiscus/webpack-remove-empty-scripts/pull/6

javascript + gulp + babel + webpack. error: Module not found: Error: Can't resolve 'babel-loader'

I'm creating a javascript project. To create it I'm using gulp and babel.
My problem is that I can't develop my code over multiple file, so I'm search a solution to 'enable' importing. At the moment I'm trying to configure webpack.
The Gulp Task is this:
gulp.task('webpack', () => {
return webpack_stream(webpack_config)
.pipe(rename('webpack_code.js'))
.pipe(gulp.dest('.build/asset/webpack/'));
});
The webpack.config.js is this:
module.exports = {
entry: ['./src/asset/js/main.js'],
output: {
filename: 'bundle.js',
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js)$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: [
['env', 'stage-0',{ modules: false }],
],
},
},
],
},
resolveLoader: {
modules: ['./node_modules'],
},
resolve: {
modules: ['./node_modules'],
},
target: 'node',
};
My current error is this:
Error in plugin 'webpack-stream'
Message:
multi ./src/asset/js/main.js
Module not found: Error: Can't resolve 'babel-loader' in ...
What's wrong?
Another Question: What's I have to put as value of entry key? Only the entry point js file or the whole files of the project?
Thanks!!
What's wrong?
I'd guess that in your project, your Webpack instance is not finding the babel loader because of your config / environment specific issues.
I've had the exact same issue as you. Here are some troubleshooting steps for to check first:
See if babel-loader is actually installed. I know it is simple, but it can save you time.
Check which Webpack/Babel versions you're dealling with in your package.json file. I'm using Webpack 4 and Babel 8. Sounds like some newer versions doesn't accept this: use: 'babel' in your webpack.config file. You need to ensure that the -loader is being used as it follows: use: 'babel-loader'.
Reinstall your node_modules folder. Sometimes it works.
Another Question:
What's I have to put as value of entry key?
Only the entry point js file or the whole files of the project?
Accordingly to Webpack's docs:
The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. - Webpack Ref
Considering that, you should pass to the entry object, the path of a folder or a file that will be used to generate your final JS file with all your modules in it.
If you have nested files, that you don't import as modules, I think you'll have to head to the docs and see this specific case.
But if this files are nested and are being imported as modules, in your entry file/folder, they will be generated in the output file.
I know it's not much but following these steps, helped me to solve it. :)

React webpack / browserify "unexpected token"

I have this npm module that I created and every time I try to include it to see if it works I get this error:
Unexpected token <
You may need an appropriate loader to handle this file type.
I've used react-starterkit and included it in main.js like so
var ReactDOM = require('react-dom');
var ColorPicker = require('color-picker-react');
ReactDOM.render(<ColorPicker />, document.getElementById('app'));
then when i run gulp which runs webpack I get the error. Here's the webpack.config.js
module.exports.getConfig = function(type) {
var isDev = type === 'development';
var config = {
entry: './app/scripts/main.js',
output: {
path: __dirname,
filename: 'main.js'
},
debug : isDev,
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}]
}
};
if(isDev){
config.devtool = 'eval';
}
return config;
}
I've tried everything I could think of and still can't get it to work. I'm not using ES6 anywhere and I've tried many different react starter kits but I just can't get it to work. Please help!!!
P.S. I am able to get the project to run when I clone it locally and build out app.js with browserify like so: browserify -t [ babelify --presets [ react ] ] app.js -o bundle.js
To solve the problem you need to remove the line exclude: /node_modules/ if you are not the author of the npm module (But you should go with another module).
The component color-picker-react doesn't seem to have a release build or script that compile the jsx. So you need to do it by your own and compile the jsx file on the fly using wepack.
Instead of just removing the exclude: /node_modules/
You can exclude all /node_modules/ except the /node_modules/color-picker-react folder by using a regex pattern :
//will exclude all modules except `color-picker-react`
exclude: /node_modules\/(?!color-picker-react).*\//,
EDIT Basics for creating a npm module:
A correct setup for a npm module is to add a prepublish script to
ensure compilation happens automatically before uploading to NPM.
Thus when you push your module to npm the users doesn't need to compile the module they can just require it.
Taking an example of a node_module:
https://github.com/securingsincity/react-ace/blob/master/package.json
The package.json file is saying which file is the entry point when you required the module
"main": "lib/ace.js",
You can see in the github repository that the lib folder doesn't exist because added to the .gitignore but the line
"prepublish": "npm run clean && npm run build"
is run before uploading to NPM so on the npm repository the lib/ folder exist and you can see it when you do npm install --save react-ace the lib folder appears in the node_modules/react-ace/ folder
A great link that explains how to build npm modules in es6 for example http://javascriptplayground.com/blog/2015/10/authoring-modules-in-es6/
EDIT explain what needs to be done on react-color-picker module :
Sorry i didn't see that you was the author of the module so you should go with the solution below.
The react-color-picker for example doesn't have a prepublish script and the main file is index.js which is
var ColorPicker = require('./colorpicker.js'); // require a file with jsx will throw an error if not precompiled
module.exports = ColorPicker;
So a syntax error is thrown.
To be able to use the npm module in your other applications :
Create a webpack config for the npm module to handle the conversion of your react component written using jsx (you can take some of the webpack configs of this module https://github.com/securingsincity/react-ace set libraryTarget: 'umd' you module will be more easy to consume from various module systems (global, AMD, CommonJS).)
add a prepublish script that output a precompiled version of the color picker (lib/pickedprecompiled.js)
change the main to "main": "lib/pickedprecompiled.js",

"ReferenceError: Can't find variable: require" (using babel.js output) [duplicate]

When this code (generated from babel) runs I get an error exports is undefined
Object.defineProperty(exports, '__esModule', {
any ideas?
You are most likely not executing the code in an environment that supports CommonJS modules. You could use a bundler, such as Browserify or webpack
to bundle your modules into something that can be run in different environments.
Or you could choose a different module transformer.
With webpack
Run npm install -g webpack; npm install -D babel-loader. Then with this webpack configuration:
// webpack.config.js
module.exports = {
entry: "./path/to/entry/module.js",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader"}
]
}
};
running the webpack command will convert all *.js files reachable via the entry file with babel and bundle them together into bundle.js.
I read an article about how ES6 import and export are only supposed to work in browser with "statically analyzable files" and Babel removed import and export support in the browser because of this. Something to do with async or possibly security?
If you want to skip the server-side bundling for dev purposes, you can put
window.MyModule = MyModule at the bottom, then import
var MyModule = window.MyModule at the top of your next file

Categories

Resources