Making a library importable using webpack and babel - javascript

I am trying to publish a package on npm (this one) that I am developing using webpack and babel. My code is written in ES6. I have a file in my sources, index.js, that (for the moment) exports one of my library's core components, it simply goes like this:
import TheGamesDb from './scrapers/thegamesdb';
export { TheGamesDb };
I am using webpack and babel to create a dist index.js that is my package's main file. My webpack.config.js goes like this:
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: {
index: ['babel-polyfill', './src/index.js'],
development: ['babel-polyfill', './src/development.js']
},
output: {
path: '.',
filename: '[name].js',
library: 'rom-scraper',
libraryTarget: 'umd',
umdNamedDefine: true
},
devtool: 'source-map',
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }
]
},
target: 'node',
externals: [nodeExternals()]
};
Now when I load my package in another project and try to import my export TheGamesDb simply like this
import { TheGamesDb } from 'rom-scraper';
I get the error
Uncaught TypeError: Path must be a string. Received undefined
It is to be noted that I am importing my library in electron.
Update: Electron seems to be the main problem here and it is not even my library but a dependency that throws this error (only in Electron)

The problem wasn't any of the things in my question but node-expat not working in electron. I switched to an alternative library and it's all right now.

Related

Excluding node_module from being written to the output file in webpack

I am trying to transpile es6 code to es5 using webpack and babel and in the js file I am importing jquery as below:
import $ from 'jquery';
So when I am building the code using webpack, the output file is getting the content of jquery along with the original transpiled code which I don't want to consume. I have added the exclude statement below to webpack.config.js but that doesn't seem to exclude the jquery part from getting appended.
exclude:path.resolve(__dirname, 'node_modules'),
Here's what the webpack.config.js file looks like:
var path = require('path');
module.exports = {
entry: {
copystyles: './src/copystyles.js',
docErrorReporter: './src/docErrorReporter',
},
output: {
path: path.resolve(__dirname, 'lib'),
filename: "[name].js",
},
mode:'none',
module: {
rules: [
{
test: path.join(__dirname, 'src'),
exclude:path.resolve(__dirname, 'node_modules'),
use: ['babel-loader']
}
]
}
};
Can anybody tell me if I am missing something here?
Thanks!

Plotly with webpack

I have installed plotly using npm i plotly.js
Added the line import 'plotly.js/dist/plotly' to my plotly import file
Then in webpack followed the instructions here to bundle the files client side.
Added in a custom js file to test plotly
Then added in the plotly scripts to my html page with the package coming first then my custom js.
However I get the error message ReferenceError: Plotly is not defined.
To test I was using the javascript code from this example. I can get it working when I save the file locally found on the plotly site here but not with webpack.
Is there something I am missing or doing wrong? My other packages seem to work fine and I can see plotly.js has successfully been added into the relvent folder client side.
webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: {
uibundles: path.resolve(__dirname, 'frontend.js'),
plotly: path.resolve(__dirname, 'plotlyimport.js'),
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'public/js')
},
plugins: [new MiniCssExtractPlugin({
filename: '../css/[name].css',
})],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.js$/,
loader: 'ify-loader'
},
]
}
};
You probably need to use webpack resolve (here) to add the details
Could you try this:
resolve: {
modules: ['node_modules'],
extensions: ['.js']
},
It seems like you need to use webpack externals to solve this issue.
webpack externals : Prevent bundling of certain imported packages and instead retrieve these external dependencies at runtime.
For example, to include plotly from a CDN instead of bundling it:
index.html
<script src="../plotly.js"></script>
webpack.config.js
module.exports = {
//...
externals: {
plotly: 'plotly'
}
};
This leaves any dependent modules unchanged, i.e. the code shown below will still work:
var Plotly = require('plotly.js');
..
..
Plotly.newPlot('myDiv', data, layout, config );
Refer to webpack externals for more details.

creating javascript library with webpack

I don't understand why this is being so complicated I want my project to have 2 separate work spaces where one is a library that will be distributed and the other will be used for testing... this is how i have the file structure
project
--engine
---math
----vec2.js
---dist
----library.js
---main.js
--sandbox
---main.js
I want to build the "engine" project with webpack and es6 modules so I get a "library" file that can be used in "sandbox".
The "engine" main file would look something like this
import vec2 from './math/vec2';
export default class Library {
constructor() {
this.vec2 = vec2;
}
}
An then the sandbox main file would look something like this
import lib from '../engine/dist/library';
const game = new lib();
The problem is when I build the "library.js" file with webpack and import it in the "sandbox" main file I can't call any of the classes therein. I get this error.
Uncaught TypeError: o.default is not a constructor
at Object.<anonymous> (library.js:1)
at e (library.js:1)
at library.js:1
at library.js:1
My webpack.config.js file looks like this
var webpack = require('webpack');
module.exports = {
context: __dirname,
entry: __dirname+"/main.js",
output: {
path: __dirname+"/dist",
filename: "library.js"
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
};
I must be missing some configuration webpack needs or some plugin that will make this work. I simply want to build the library with webpack using es6 modules so it can be used in another project but I have no idea how to configure it. I'm using babel for transpilling es6 to es5
You need to configure output.libraryTarget. In this case the target commonjs-module is appropriate. So your output would be:
output: {
path: __dirname+"/dist",
filename: "library.js",
libraryTarget: "commonjs-module"
},
The different targets are described in the docs. And you might also want to read Guides - Authoring Libraries.

ES6 Webpack Relative imports - Module not found: Error: Cannot resolve module

I'm trying to find some information about Webpack and relative imports when working with ES6 and Babel.
I have an import line in a simple entry point in my app:
// app.es6
import * as sayHello from 'sayHello';
console.log(sayHello());
sayHello.es6 is the same directory as app.es6. (The contents of sayHello.es6 is not significant).
When I run the Webpack compiler via the command line:
$ webpack
I get the following error:
ERROR in ./app/app.es6
Module not found: Error: Cannot resolve module 'sayHello' in /Users/username/Code/projectname/app
This is solved by setting the path to relative:
// app.es6 - note the ./ in the import
import * as sayHello from './sayHello';
console.log(sayHello());
This is a bit of a pain because it's different to the example es6 code on Babel website under the Modules section.
Here is my Webpack config:
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: [
'babel-polyfill',
'./app/app.es6'
],
output: {
publicPath: '/',
filename: './dist/app.js'
},
debug: true,
devtool: 'source-map',
module: {
loaders: [
{
test: /\.js|\.es6$/,
exclude: /node_modules/,
loader: 'babel-loader',
query:
{
presets:['es2015']
}
}
]
},
resolve: {
extensions: ['', '.js', '.es6'],
},
};
Question: Does any one know why there is this difference? Or where the relevant information regarding ES6 module imports is in the Webpack documentation?
This is by design, without prefixing it indicates the module should be loaded from node_modules directory. You can set up an alias in your webpack config which would remove the need for relative module imports
resolve: {
alias: {
sayHello: '/absolute/path/to/sayHello'
},
extensions: ['', '.js', '.es6']
}
Then Webpack would fill in the gaps in your import statements and allow you to omit the relative path and import * as sayHello from 'sayHello'; would work throughout your project

Webpack throws syntax error for JSX

When I attempted to use webpack to compile my react jsx code, I received the following error:
ERROR in ./client/index.js
Module parse failed: C:\Users\Gum-Joe\Documents\Projects\bedel/client\index.js Unexpected token (6:11)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (6:11)
at Parser.pp.raise (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:920:13)
at Parser.pp.unexpected (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:1483:8)
at Parser.pp.parseExprAtom (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:330:12)
at Parser.pp.parseExprSubscripts (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:225:19)
at Parser.pp.parseMaybeUnary (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:204:17)
at Parser.pp.parseExprOps (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:151:19)
at Parser.pp.parseMaybeConditional (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:133:19)
at Parser.pp.parseMaybeAssign (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:110:19)
at Parser.pp.parseExpression (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:86:19)
at Parser.pp.parseReturnStatement (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:1854:26)
at Parser.pp.parseStatement (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:1719:19)
at Parser.pp.parseBlock (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:1991:21)
at Parser.pp.parseFunctionBody (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:607:22)
at Parser.pp.parseMethod (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:576:8)
at Parser.pp.parseClassMethod (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:2137:23)
at Parser.pp.parseClass (C:\Users\Gum-Joe\Documents\Projects\bedel\node_modules\acorn\dist\acorn.js:2122:10)
# ./client/index.js 1:0-20
.babelrc:
{
"presets": ["es2015", "react"]
}
webpack.config.js:
// Webpack config
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// Use client as our root
context: __dirname + "/client",
// Entry file
entry: "./index.js",
// Resolve
resolve: {
extensions: ['', '.js', '.jsx']
},
// Output to /build
output: {
path: path.join(__dirname, "build", "js"),
filename: "bundle.js"
},
loaders: [
{ test: /\.jsx$/, exclude: /node_modules/, loader: "babel-loader" }
],
// Plugins
plugins: [
// HTML
new HtmlWebpackPlugin({
title: 'Bedel',
filename: path.join(__dirname, 'views', 'index.ejs'),
template: path.join(__dirname, 'client', 'templates', 'index.ejs')
})
]
};
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render () {
return <p> Hello React</p>;
}
}
ReactDOM.render(<App/>, document.getElementById('app'));
I have installed all the babel presets required, as well as babel-core.
I have looked at the following answers already:
babel-loader jsx SyntaxError: Unexpected token
React, babel, webpack not parsing jsx code
Edit: After commenting out my jsx syntax, the outputting bundle.js does not appear to have been transformed by babel (i.e. I can see ES6 code in it)
Edit: Sorry for the inconvenience, but app.jsx was a solution that I tried that involved putting the logic that should be in index.js into a separate file.
Edit: Here is a list of the solutions I tried that did not work:
Copy .babelrc to client/.babelrc
Change test to test for .js instead of .js
Separate app logic into separate file (app.js)
Put presets to use in webpack config
Also, I have pushed my code to my GitHub repo (https://github.com/Gum-Joe/bedel). Feel free to have a look at it.
You configured the loader to only pass .jsx files through Babel:
test: /\.jsx$/
However, your file has the extension .js. Either rename the file or update the test expression to /\.jsx?$/.
In addition to updating the test, you need to rename .babel.rc to .babelrc (no . before rc). Otherwise Babel thinks that there is no configuration file and won't load any presets.
The loaders property must exist within the module property. Webpack Loaders
module.exports = {
// ...
// Output to /build
output: {
path: path.join(__dirname, "build", "js"),
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.jsx$/, exclude: /node_modules/, loader: "babel-loader" }
]
},
//...
};
You need to use react-preset with babel, like here:
loaders: [{
test: /\.(js|jsx)$/,
loader: 'babel',
query: {
presets: [
'es2015',
'react'
]
}
}]
I'm having this issue as well, and if you're using Windows and Node 6.x, the only workaround I've found for now seems to be to use Node 4 LTS or 5 instead. Without knowing the root cause, the problem seems to stem from some combination of using JSX, Webpack, Babel, Acorn JS, Node 6, and Windows.
https://github.com/coryhouse/pluralsight-redux-starter/issues/2
https://github.com/danmartinez101/babel-preset-react-hmre/issues/32
Can you try wrapping the entire element in brackets "()"?
return (<p>...</p>)

Categories