Webpack bundle imports with an # - node.js

I am trying to bundle a Node Express server built with TypeScript using Webpack.
Compiling/Transpiling into one JavaScript file server.js works well, but the file does not seem to have all necessary imports included. If the file is in dist/server.js and there are still Node modules in node_modules/..., then starting the server using node dist/server.js works well. But if I copy the server.js to any other location without also copying the Node modules, and then start it, it does not find classes imported with an #.
Possible error:
mysystem:Desktop myuser$ node server.js
internal/modules/cjs/loader.js:582
throw err;
^
Error: Cannot find module '#overnightjs/core'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:580:15)
at Function.Module._load (internal/modules/cjs/loader.js:506:25)
at Module.require (internal/modules/cjs/loader.js:636:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object.<anonymous> (/Users/myuser/Desktop/server.js:1:1422)
at a (/Users/myuser/Desktop/server.js:1:172)
at Object.<anonymous> (/Users/myuser/Desktop/server.js:1:6473)
at a (/Users/myuser/Desktop/server.js:1:172)
at Object.<anonymous> (/Users/myuser/Desktop/server.js:1:6233)
at a (/Users/myuser/Desktop/server.js:1:172)
I think that I might have something missing in my Webpack configuration file, which is:
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: "./src/start.ts",
output: {
filename: "server.js",
path: path.resolve(__dirname, "dist")
},
node: {
// Need this when working with express, otherwise the build fails
__dirname: false, // if you don't put this is, __dirname
__filename: false, // and __filename return blank or /
fs: 'empty',
},
resolve: {
alias: {},
// Add '.ts', and '.tsx' as resolvable exteensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},
externals: [nodeExternals()], // Need this to avoid error when working with Express
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
]
},
plugins: [
new CleanWebpackPlugin({
cleanAfterEveryBuildPatterns: ['dist']
})
]
};
The versions I use:
Node (v10.13.0)
yarn (1.7.0)
Express (4.17.1)
TypeScript (3.7.4)
Webpack (4.41.4)
Webpack-CLI (3.3.10)
How can I also add imports starting with an # into the bundle in Webpack?

It is make sense, Your externals config tells webpack not to bundle node_modules into the bundle but require them at run time.
This means that if you are not copying node_modules to the new location, it will try to require it, and will fail.
Usually it is best practice not to bundle node_modules whenever you are creating a node bundle.
You have 2 choices:
Remove externals config - will increase bundle size cause it will contain all the node_modules that your app is using.
Installing a fresh node_modules on you new location, if this location is a production env, you can use npm install --production which will install only the dependencies without devDependencies.

Don't bundle modules when transpiling TypeScript. Standard practice is two download modules wherever you've deployed you server. Make sure to use the production flag if you're all done developing. npm i --production

Related

webpack doesn't bundle node modules

I want to require a module from node_modules and I want to bundle it (for test purposes), but Webpack behaves as if it is added to externals.
// no externals or any plugin used
let config = {
mode: 'none',
target: 'node',
entry: {
output: `/example.js`,
},
resolve: {
extensions: ['.js'],
},
output: {
path: './dist',
},
};
// exampl.js
require('path')
// dist/output.js
require('path');
Expected behavior
the node module path to be bundled
actual behavior
Webpack keep require('path');
This is by design. When you set target: 'node' in webpack config, webpack will not bundle the built-ins module of Node.js. path is a built-in module of Node.js, it doesn't come from the node_modules directory.
using node webpack will compile for usage in a Node.js-like environment (uses Node.js require to load chunks and not touch any built in modules like fs or path).
See targets

How to bundle node module CSS into a vscode extension

My Visual Studio Code extension uses the node module highlight.js which comes with a folder full of CSS files. These provide colour schemes for syntax colouring. It has become necessary to bundle some of the CSS files.
It's about bundling an asset
The objective is to bundle a CSS file and at run-time access the file content as a string. If that can be achieved without an import statement that would be perfect. Normally, how exactly one accesses the content of the bundled file would be a separate question, but I have a feeling that content retrieval and how one should go about bundling the asset are closely entwined.
I freely admit to having a weak understanding of WebPack.
The story so far
The bundler is specified in package.json as "webpack": "^5.4.0" but I don't know how to ascertain what is actually present. It is conceivable that there is something wrong with my setup: when I try to run webpack --version on a command prompt in the project folder, it responds
CLI for webpack must be installed.
webpack-cli (https://github.com/webpack/webpack-cli)
We will use "npm" to install the CLI via "npm install -D webpack-cli".
Do you want to install 'webpack-cli' (yes/no):
The first time this happened I responded yes. After a flurry of installation and another try the same thing happened. However, vsce package has no trouble using webpack for a production build and pressing F5 to debug successfully puts together a development build in a dist folder with an unminified file I can examine (which is how I know the file mentioned below is being bundled).
Moving on from there I've modified webpack.config.js like so
//#ts-check
'use strict';
const path = require('path');
/**#type {import('webpack').Configuration}*/
const config = {
target: 'node', // vscode extensions run in a Node.js-context -> https://webpack.js.org/configuration/node/
entry: './src/extension.ts', // the entry point of this extension, -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'dist' folder (check package.json), -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
filename: 'extension.js',
libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../[resource-path]'
},
devtool: 'source-map',
externals: {
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, -> https://webpack.js.org/configuration/externals/
},
resolve: {
// support reading TypeScript and JavaScript files, -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js', '.css']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
}
};
module.exports = config;
As you can see there are rules and loaders for CSS.
When I add this import
import "../node_modules/highlight.js/styles/atelier-dune-light.css";
webpack happily builds the bundle and when I inspect it I can find the bundled CSS.
However, when I try to load the extension in the extension debug host, it fails to load, with this message.
Activating extension 'pdconsec.vscode-print' failed: document is not defined.
Enabling break on caught exceptions reveals this rather surprising exception.
Exception has occurred: Error: Cannot find module 'supports-color'
Require stack:
- c:\Users\Peter\AppData\Local\Programs\Microsoft VS Code\resources\app\node_modules.asar\get-uri\node_modules\debug\src\node.js
- c:\Users\Peter\AppData\Local\Programs\Microsoft VS Code\resources\app\node_modules.asar\get-uri\node_modules\debug\src\index.js
- c:\Users\Peter\AppData\Local\Programs\Microsoft VS Code\resources\app\node_modules.asar\get-uri\dist\index.js
- c:\Users\Peter\AppData\Local\Programs\Microsoft VS Code\resources\app\node_modules.asar\vscode-proxy-agent\out\agent.js
- c:\Users\Peter\AppData\Local\Programs\Microsoft VS Code\resources\app\node_modules.asar\vscode-proxy-agent\out\index.js
- c:\Users\Peter\AppData\Local\Programs\Microsoft VS Code\resources\app\out\bootstrap-amd.js
- c:\Users\Peter\AppData\Local\Programs\Microsoft VS Code\resources\app\out\bootstrap-fork.js
OK, so activation failed because the loader barfed. But WTF does importing CSS have to do with support-color?
Remove the import and it runs just fine. I really don't know how to respond to this; it's not clear to me why a demand for a stylesheet should cause that error. At this point I look to others for guidance and advice.
Remove style-loader from webpack.config.js to fix the error.
Pull the CSS as a string like this. Note the abbreviated path.
const cssPath: string = "highlight.js/styles/atelier-dune-light.css";
const theCss: string = require(cssPath).default.toString();
You do not need the import statement, the use of require will cause Webpack to bundle the files, but you still have to remove style-loader to avoid the loader error.

How to build a ES6 express app with webpack 2 and babel?

Given the following Webpack 2 configuration, I want to write a express app using ES6. My .babelrc has only the es2015 preset:
const path = require('path');
module.exports = {
target: 'node',
entry: path.resolve(__dirname, 'src', 'server.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'server.bundle.js',
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader',
},
],
},
};
Running webpack and starting the server work fine, but when accessing the URL through the browser I get the following error:
Error: Cannot find module "."
at webpackMissingModule (/Users/Me/project/dist/server.bundle.js:18208:74)
I don't know whether it's due to the . in a require('./some/other/file') call (not all files are ES6, so these one use require() instead of import); or maybe some configuration I'm missing.
And also, given that stack trace I can't really map it to the original source file.
Thanks in advance
Update 1
I just realize I'm trying to use webpack to transpile ES6 code because I'm trying to replicate another build task (the one in mern.io), but I could do the same just with babel. Maybe there's no reason for using webpack on the serverside.
You need to install and add in webpack.config.js ExternalsPlugin:
plugins: [
new ExternalsPlugin({
type: 'commonjs',
include: path.join(__dirname, './node_modules/'),
}),
],
It helped me, I hope you too, because I spent a lot of time for solutions this problem)
Maybe the reason is that you are using target: "node" on webpack config. So that means it's creating your package for nodejs environment. Can you test after changing it to target: "web" for client transpile?
https://webpack.js.org/concepts/targets/

Reactjs: Unexpected Token

I'm trying to follow the tutorial here: https://facebook.github.io/react/docs/getting-started.html
Simply trying to build the following, either within Sublime Text 3, or webpack:
// ReactTest.js
var React = require('react');
var ReactDOM = require('react-dom');
console.log("Hello");
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
I've installed Sublime Text 3, as well as the following packages via Package Control, Install:
Babel for syntax highlighting
Sublime Linter (3) for error checking
Sublime Linter-contrib-eslint (an interface for eslint)
I have already installed node via homebrew:
brew install node
Used NPM to install the following:
npm install webpack -g
npm install --save react react-dom babel-preset-react babel-preset-es2015
npp install jsxhint -g
npm install -g jshint
From what I understand, this should be everything I need to run either of the two options:
Use Sublime Text 3's build: I added a new 'build system' for Sublime Text by Tools -> Build System -> New Build System and created the file:
{ "cmd" : ["/usr/local/bin/node", "$file"], "selector":"source.js" }
which is saved to me/Library/ApplicationSupport/SublimeText3/Packages/user/node.sublime.build on my osx.
I run Tools -> Build to build which results in:
/Users/me/Desktop/Test/ReactTest.js:8
<h1>Hello, world!</h1>,
^
SyntaxError: Unexpected token <
at exports.runInThisContext (vm.js:73:16)
at Module._compile (module.js:443:25)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
[Finished in 0.1s with exit code 1]
[cmd: ['/usr/local/bin/node', '/Users/me/Desktop/Test/ReactTest.js']]
[dir: /Users/me/Desktop/Test]
[path: /usr/bin:/bin:/usr/sbin:/sbin]
Also tried to do the same thing using webpack with the following command:
webpack ReactTest.js Bundle.js
Which results in:
ERROR in ./ReactTest.js
Module parse failed: /Users/me/Desktop/Test/ReactTest.js Line 8: Unexpected token <
You may need an appropriate loader to handle this file type.
|
| ReactDOM.render(
| <h1>Hello, world!</h1>,
| document.getElementById('example')
| );
Can anyone tell me what I'm doing wrong?
EDIT: Completely new to all of these technologies. Here's a screenshot of my project in Sublime Text.
EDIT 2: The .babelrc file, which I've copied from the web:
{
"plugins": ["transform-react-jsx"],
"ignore": [
"foo.js",
"bar/**/*.js"
]
}
If you are using JSX in your code, you have to transpile to js using loaders in webpack.
module.exports = {
entry: 'ReactTest.js',
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /.js$/,
exclude : /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}
]
}
};
Make sure you configured .babelrc in root path if you are using ES2015 syntax
copy and use the below webpack config in your webpack.config.js
run webpack in root folder
include bundle.js in your index.html.
Let me know if you face any difficulties

Resolve the module loaded by plugin in Webpack config

The following example will work only if some-module module is Node module, and won't work for modules loaded by Webpack plugin.
How can Webpack's own logic (enhanced-resolve) be used to resolve module paths in config?
In my case it was bower-webpack-plugin, but I guess this should work in the same way with any ResolverPlugin
var BowerWebpackPlugin = require("bower-webpack-plugin");
module.exports = {
...
module: {
plugins: [new BowerWebpackPlugin()],
loaders: [
{
// this won't work
test: require.resolve("some-bower-module")
loader: "imports?this=>window"
}
]
};
require.resolve inside webpack.config.js is resolved by Node and not Webpack's resolver. You can use require("path").resolve("path/to/bower/module") to get the full path to your Bower module.

Resources