npm link with webpack - cannot find module - javascript

I'm trying to npm link a module to a project using webpack as its bundler. Of course, after trying many things, I keep getting this error:
ERROR in ./src/components/store/TableView.jsx
Module not found: Error: Cannot resolve module 'react-bootstrap-table'
Here are the exact steps I take when doing this:
1.) cd ../forks/react-bootstrap-table
2.) npm link
(success, checked ~/.nvm/.../node_modules/react-bootstrap-table for symlink and it's there)
3.) cd ../../projRoot/
4.) npm link react-bootstrap-table
(no errors thrown?, says successful link)
5.) node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js
Solutions I've tried:
- https://webpack.github.io/docs/troubleshooting.html
- How to make a linked component peerDepdencies use the equivalent node_modules of the script being linked to?
- And many purple links on google serps
webpack.config.js
const webpack = require('webpack')
const path = require('path')
const ROOT_PATH = path.resolve(__dirname)
module.exports = {
devtool: process.env.NODE_ENV === 'production' ? '' : 'source-map',
entry: [
'webpack/hot/only-dev-server',
'./src/index.js'
],
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot','babel']
},
{
test: /\.scss$/,
loaders: ['style','css','sass'],
exclude: /node_modules/
},
{
test: /\.css$/,
loaders: ['style','css']
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader'
}
]
},
resolve: {
extensions: ['', '.js', '.jsx'],
fallback: path.resolve(__dirname, './node_modules')
},
resolveLoader: {
fallback: path.resolve(__dirname, './node_modules')
},
output: {
path: process.env.NODE_ENV === 'production' ? path.resolve(ROOT_PATH, 'app/dist') : path.resolve(ROOT_PATH, 'app/build'),
publicPath: '/',
filename: 'bundle.js'
},
devServer: {
contentBase: path.resolve(ROOT_PATH),
historyApiFallback: true,
hot: true,
inline: true,
progress: true,
stats: 'errors-only',
host: '192.168.1.115'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}
Notes:
1. this is the only symlink in the project
2. I run npm install inside forked version (also tried without, doesn't work)
3. I use NVM, but I have used symlinks before without webpack successfully.
I've been at this for a few days now, any help will be much appreciated.

I was facing a similar issue with webpack and ended up by adding this my webpack.config.js:
module.exports = {
resolve: {
symlinks: false
}
};
Here is the link to webpack docs. Since your question there happened a lot to webpack and their api, so I do not know how much relevance my answer still has according to your question. But for people facing this or a similar issue today this could be a solution. As to be seen, there are still people complaining about:
Webpack GitHub Issue 1643
Webpack GitHub Issue 1866

Also make sure you have bundle and yarn installed and executed in the linked package

Okay guys, this is specific to my use case, but make sure to follow all the instructions to completely build the library you are symlinking. Initially, I a npm install and gulp build, but that wasn't enough. I had to run a few extra commands to get the library to fully build.
Now it works! If you are still having issues, go through the documentation for each library you are symlinking, and use my webpack config as a template for resolving external libraries.

Just in case it's useful for others, the solution of adding the resolve.symlinks configuration to false suggested by #Beat was not enough in my case, I had to perform the following steps to solve it:
In the library:
Setup the libraries that are generating issues as peerDependencies in the package.json instead of dependencies or devDependencies, e.g. in my case react:
"peerDependencies": {
"react": "^16.8.6",
...
}
run npm install
build the library (in my case, with a rollup -c npm script
In my main app:
change the version of my library to point to my local project with a relative path in package.json, e.g.
"dependencies": {
"my-library": "file:../../libraries/my-library",
...
}
Add resolve.symlinks = false to my main app's webpack configuration
Add --preserve-symlinks-main and --preserve-symlinks to my package.json start script, e.g:
"scripts": {
"build": "set WEBPACK_CONFIG_FILE=all&& webpack",
"start": "set WEBPACK_CONFIG_FILE=all&& webpack && node --preserve-symlinks-main --preserve-symlinks dist/server.js",
}
run npm install
run npm run start

Related

Are typescript project references necessary if transpiling with babel? (Electron project with Webpack)

I am still in the process of setting up my project configuration so I don't have any errors to work with right now, but if I am understanding the Typescript docs correctly...
It seems like Project references TypeScript Docs - Project references are not that necessary if transpiling with babel-loader in webpack. (I'm working in VSCode)
I am trying to convert an Electron app to TypeScript and currently reorganizing the folder structure so I have minimal issues.
I am trying to understand if I am on the right track and if I can avoid including "references" and instead just use "extends" to get the functionality I want.🤔
Here is my project structure ignoring all files that are not tsconfig files:
./tsconfig.json
./tsconfig-base.json
./main/tsconfig.json
./src/client/tsconfig.json
./__tests__
./__tests__/__client__/tsconfig.json
./__tests__/__main__/tsconfig.json
In this structure ./tsconfig.json would really just be for references like the example on Microsoft's Github
Electron Main Process and related files are in ./main. The tsconfig here will set "module":"commonjs" for working in node. I think it will also extend from the ./tsconfig-base.json
Electron Renderer Process and my React-Redux app files are in ./src/client. The tsconfig here sets "module":"es2015" or "module":"ESNEXT" for working with es modules. I think it will also extend from the ./tsconfig-base.json
The ./__tests__/__client__/tsconfig.json and ./__tests__/__main__/tsconfig.json would just be duplicates of the non tests folder versions similarly extending from the base config in ./
Webpack config is already set up to handle creating separate bundles for main and renderer processes so that the entire app can be in TypeScript. Is there any reason I should be using "references" in my files in the main or client folders?
Sample snippets of the Webpack config before I switch the tnry files to be .ts files (dev):
const rendererInclude = path.resolve(__dirname, "src");
const mainInclude = path.resolve(__dirname, "main");
Main Process:
module.exports = [
{
mode: "development",
entry: path.join(__dirname, "main", "swell.js"),
output: {
path: path.join(__dirname, "dist"),
filename: "main-bundle.js",
},
target: "electron-main",
node: {
__dirname: false,
__filename: false,
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".json"],
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
loader: "babel-loader",
include: mainInclude,
exclude: /node_modules/,
}
] } ... },
continued to Renderer Process:
{
mode: "development",
entry: path.join(__dirname, "src", "index.js"),
output: {
path: path.join(__dirname, "dist"),
filename: "renderer-bundle.js",
},
target: "electron-renderer",
resolve: {
extensions: [".ts", ".tsx", ".js", ".json"],
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
loader: "babel-loader",
include: rendererInclude,
exclude: /node_modules/,
]} ...} ]
Project Reference will help you solve some problems in case where your test projects import src/main modules.
This is what Project Reference solves:
There’s no built-in up-to-date checking, so you end up always running tsc twice
Invoking tsc twice incurs more startup time overhead
tsc -w can’t run on multiple config files at once
read more about Project References

BabelJS is processing the wrong files when working with Webpack 4

I started from a configuration consisting of both webpack 3 and a similarly old babel version. It can be found in the following repo:
https://github.com/konradmi/react-loadable-ssr-code-splitting
I updated both webpack and babel to their latest versions, as well as all the node modules, and migrated the old configuration accordingly. This issue could stem from any of these.
Once I finished migrating, I noticed all the babel plugins traverse my webpack configs files (which are in a separate nested folder) instead of the actual js source files which are properly processed by webpack. (I verified it by doing some logging inside of the babel plugins).
The result is the same regardless of whether I'm using .babelrc or not.
The webpack config files used to be at the root of the project as you can see in the repo I linked to above, and now they are inside of a nested "config" folder.
At first I thought it might be the cause of this issue, so I tried the following:
Using path.resolve() in the entry point in order to use an absolute path to make sure it wouldn't possibly be re-interpreted by babel from a string relative to who knows where.
Putting the webpack config files back in the root of the project and building from that path.
In all the variations I've tried - webpack always does its job perfectly, while babel is traversing the wrong files. I'm not even sure how it's possible, babel-loader should be traversing the files which it got from the previous webpack rule, which emitted the correct files.
Here's my current Webpack 4 config files concatenated into 1 file and stripped of irrelevant rules and plugins for your convenience:
const webpack = require('webpack')
const path = require('path')
const webpackNodeExternals = require('webpack-node-externals')
module.exports = {
name: 'server',
target: 'node',
externals: [webpackNodeExternals()],
entry: './src/server.tsx',
output: {
filename: 'bundle.js',
chunkFilename: '[name].js',
path: path.resolve(__dirname, '../build')
},
mode: 'development',
stats: 'verbose',
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
babelrc: false,
presets: [
[
'#babel/env',
{
'targets': {
'browsers': ['last 2 versions']
},
'debug': false
}
],
'#babel/preset-react'
],
plugins: [
'#babel/plugin-syntax-dynamic-import',
'#babel/plugin-proposal-class-properties',
'#babel/plugin-transform-object-assign',
'react-loadable/babel'
]
}
}
]
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
}
}
I was importing webpack in my server source code, the files babel was going over were webpack imports which I added there in the source code. It couldn't find anything else other than those imports because due to previous rules webpack was exporting a bundle with evals containing the processed code (dev mode settings). The babel plugin wasn't looking for eval statements, so the only thing I could see was the processing of webpack related imports.

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.

Entry module not found: Error: Can't resolve './src/index.js'

I was installing a react startup app and added Webpack, but it says Can't resolve './src/index.js'.
Browser Shows
My Files Path and Package.json Contents
Webpack.config.js Contents
var debug = process.env.NODE_ENV !== "production";
var webpack = require('webpack');
var path = require('path');
module.exports = {
context: path.join(__dirname, "public"),
devtool: debug ? "inline-sourcemap" : false,
entry: "./src/index.js",
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2016', 'stage-0'],
plugins: ['react-html-attrs', 'transform-decorators-legacy', 'transform-class-properties'],
}
}
]
},
output: {
path: __dirname + "/public/",
filename: "build.js"
},
plugins: debug ? [] : [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
],
};
Your base URL is path.join(__dirname, "public"), and your entry is ./src/index.js. Webpack tries to find ./src/index.js in public dir; obviously it does not exist. You should modify entry to ../src/index.js.
The other way I find out to fix this problem is to use path.resolve().
const path = require('path');
module.exports = {
mode: "production",
entry: path.resolve(__dirname, 'src') + 'path/to/your/file.js',
output: {
/*Webpack producing results*/
path: path.resolve(__dirname, "../src/dist"),
filename: "app-bundle.js"
}
}
This will make sure, webpack is looking for entry point in src directory.
By the way it's the default entry point. You can also change this entry point to your suitable location. Just replace the src directory with the other directory you want to use.
My webpack.config.js was named Webpack.config.js and the new cli was looking for something case-sensitive.
Webpack does not look for .js files by default. You can configure resolve.extensions to look for .ts. Don't forget to add the default values as well, otherwise most modules will break because they rely on the fact that the .js extension is automatically used.
resolve: {
extensions: ['.js', '.json']
}
The entry path is relative to the context. It's looking for a file in public/src/ when you want it to look for a path in just /src. Looking at the rest of your webpack.config.js it doesn't seem like you need the context line at all.
https://webpack.js.org/configuration/entry-context/
I had the same problem and found that it was caused by having installed create-react-app globally in the past using npm install -g create-react-app.
As create-react-app should now not be installed globally, I needed to uninstall it first using npm uninstall -g create-react-app and then install it in my project directory with npx create-react-app *my-app-name*.
My solution was to put App.js file on a components folder inside the src folder and keep the inde.js just inside the src one
I had same problem. And solutions was really 'at the top' I forgot to add module.exports inside my webpack.prod.js.
So instead of
merge(common, {
...
});
use
module.exports = merge(common, {
...
});

Pass an argument to Webpack from Node.js

I'm trying to build both minified and unminified versions of my app (js and css) using Webpack.
This can be easily done via command-line interface using -p or --optimize-minimize switch:
webpack
webpack -p
However, I would like to perform these actions with just one command, so I decided to write a small Node.js script which would run both of these Webpack builds:
var webpack = require('webpack');
var config = require('./webpack.config');
webpack(config, callback); // Build unminified version
So the question is: can I pass the aforementioned -p argument to Webpack from the Node.js script in order to build the minified version? Or maybe there is a simpler way of solving my particular problem?
Of course, I can use child_process.exec(), but I don't think it's an authentic Node.js way.
Create your default config to webpack an unminified version. Run webpack with that config. Change the configuration from code and run webpack again. Here is a code example.
var webpack = require('webpack');
//assuming the config looks like this.
var config = {
entry: "./entry.js",
output: {
devtoolLineToLine: true,
sourceMapFilename: "./bundle.js.map",
pathinfo: true,
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.css$/, loader: "style!css" }
]
},
plugins: []
};
webpack(config).run(); // Build unminified version
config.output.filename = 'bundle.min.js'
config.plugins = [
new webpack.optimize.UglifyJsPlugin({
include: /\.min\.js$/,
minimize: true
})];
webpack(config).run(); // Build minified version
Key p is an alias to setting node environment variable process.env.NODE_ENV="production" as described here

Categories

Resources