How to bundle node module CSS into a vscode extension - node.js

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.

Related

Error in ./node_modules/node-libcurl/lib/binding/node_libcurl.node

I'm a C++ developer and beginner in the Node world.
I would like to create a CEP and VUE based Photoshop plugin.
The skeleton plugin works well.
I would like to use node-libcurl package for this plugin.
I installed libcurl - It's OK.
npm i node-libcurl --save
I put down into my C4.js
const { curly } = require('node-libcurl');
When I want to build my project I got this error:
INFO Starting development server... 98% after emitting CopyPlugin
ERROR Failed to compile with 1 error
7:26:51 PM error in
./node_modules/node-libcurl/lib/binding/node_libcurl.node
Module parse failed: Unexpected character '�' (1:2)
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 (Source code omitted for > > this binary file)
# ./node_modules/node-libcurl/dist/Easy.js 5:17-60
# ./node_modules/node-libcurl/dist/index.js
# ./src/c4/C4.js
# ./src/main.js
# multi (webpack)-dev-server/client?http://192.168.1.22:8080&sockPath=/sockjs-node
(webpack)/hot/dev-server.js ./src/main.js
I tried this webpack.config.js in .... \node_modules\node-libcurl
module.exports = {
target: "node",
node: {
__dirname: false,
},
module: {
rules: [
{
test: /\.node$/,
loader: "node-loader",
},
],
},
};
... but it did not work.
I appreciate any help
Thx:
Carlos
It was my fail.
I got answer from developer.
This library is not supposed to work in the Browser, it is a backend-only library.
/Carlos

Is there a way to build node_modules using webpack on backend ( node js )?

I am using webpack 4.32 for node js. So far the code is properly built when i exclude node_modules, but i want node_modules also to be built in webpack so that when moved to cloud there is no need of installing every time.
Excluded node_modules using, externals : [ nodeExternals() ] . Then background node code builds properly without error and runs on npm start.
If i want to include node_module while build , then i added following code,
module: {
rules: [{
test: /\.node$/,
use: 'native-ext-loader'
},
// Support for *.json files.
{
test: /\.json$/,
loader: 'json-loader'
},
// all css required in src/app files will be merged in js files
{
test: /\.(scss|sass)$/,
exclude: root('src', 'style'),
loader: 'raw-loader!postcss-loader!sass-loader'
},
{test: /\.js$/,loader: 'script-loader'}
]
}
If i build using npm run build on node server, its building the file properly, but on npm start i get error " [Script Loader] ReferenceError: require is not defined ".
I have read the official webpack, which says "requires are not parsed in script loader ". Link : https://webpack.js.org/loaders
Is there any other way we can make webpack parse requires ? Any plugins , other loaders, parsers.
Expected output is node_modules should be built with code, when i run server using npm start then the application must run properly without errors.

React Developer Tools Shows "Waiting for roots to load..."

I've just switched to Preact 8.4.2 and would like to get the React Developer Tools to work as well. In my webpack.config.js, I've added:
alias: {
react: 'preact-compat',
'react-dom': 'preact-compat'
}
In my entry .js file, I've added:
require('preact/debug');
After adding these, I was getting an error when attempting to build:
Module parse failed: /myProject/node_modules/preact/src/preact.js Line 1: Unexpected token
You may need an appropriate loader to handle this file type.
| import { h, h as createElement } from './h';
| import { cloneElement } from './clone-element';
| import { Component } from './component';
# ./~/preact/debug.js 6:14-31
I only had .jsx files loading with babel-loader (not .js), so I added an additional entry in my webpack.config.js file:
{
test: /\.js$/,
include: /node_modules\/preact/,
loader: 'babel-loader'
},
After adding this entry, I'm able to build without issues, but my React Developer Tools just shows:
Waiting for roots to load...
to reload the inspector [click here]
Something is either up with your preact app or your webpack config. I just solved a similar problem.
First step, check if its your preact. If you have no console errors, drop your preact into this working boilerplate (you'll have to do a little rewiring to get it working) https://github.com/developit/preact-boilerplate
If after firing it up with your code, Devtools works as expected, then there is something wrong with your build. In that case it turns into a game of line by line updating your (mostly) working build to match preact-boilerplate.
In my case, I had included "src" in my webpack resolve. This threw no errors in terminal/console, and the build worked perfectly otherwise. Once I found it, devtools started working.

Babel not transpiling ES6 module in node_modules despite proper exclude

In a react project I used react-boilerplate but had private modules to include in the frontend that needed transpiling. In order for babel to transpile those I set exclude to the following function in the webpack config that relates to babel:
rules: [
{
test: /\.js$/, // Transform all .js files required somewhere with Babel
// eslint-disable-next-line object-shorthand, func-names
exclude: function (modulePath) {
return /node_modules/.test(modulePath) &&
!/node_modules\/#trade-quorum\/tq-helpers/.test(modulePath);
},
use: {
loader: 'babel-loader',
options: options.babelQuery,
},
},
And it worked perfectly.
Now I used that same trick in a different project but this time, in the resulting bundle tq-helpers is included but not transpiled into ES5 - the ES6 code is directly in the bundle and the build raises an error (more specifically UglifyJS).
There must be a reason around the dependencies to this package that are not the same in the two projects but hard to find. I was wondering whether there is a way to debug in details what babel does for a specific package in order to find the reason.
Thanks you for your help,
Best,
Didier

Webpack fails with Node FFI and Typescript - dynamic require error

In a simple Typescript program I require Node FFI with
import * as Electron from 'electron';`
import * as ffi from 'ffi';`
and then
mylib = ffi.Library('libmoi', {
'worker': [ 'string', [ 'string' ] ],
'test' : [ 'string', [] ]
} );
Linking that up via webpack yields
WARNING in ./~/bindings/bindings.js
Critical dependencies:
76:22-40 the request of a dependency is an expression
76:43-53 the request of a dependency is an expression
# ./~/bindings/bindings.js 76:22-40 76:43-53
The problem seems to be that FFI has a dynamic require and the fix seems to be to apply webpack.ContextReplacementPlugin in the webpack.config.js file.
This is a bit out of my reach, but an example for an Angular case is:
plugins: [
new webpack.ContextReplacementPlugin(
// The (\\|\/) piece accounts for path separators in *nix and Windows
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
root('./src') // location of your src
)
]
Any idea how to do this for FFI?
Here is the answer: github issue comment on the Johnny-Five repo
Quoting from brodo's answer, this is what you do to stop webpack getting snarled up with "bindings" and similar:
... the webpack config looks like this:
module.exports = {
plugins: [
new webpack.ContextReplacementPlugin(/bindings$/, /^$/)
],
externals: ["bindings"]
}
I also had a similar issue, somehow, I managed to resolve it. I will first explain my understanding.
Main work of webpack is to bundle the separate code file into one file, by default it bundles all the code that is referenced in its tree.
Generally two types of node_modules:
To be used on browser side(angular, rxjs etc)
To be used on nodejs side(express, ffi etc)
It is safer to bundle browser side node_module but not safer to bundle node side node_module because they are not designed like that So the solution is below two steps:
Give appropriate target(node, electron etc) in webpack.config.js file e.g "target":'electron-renderer' by default it is browser
Declare node_side module as external dependency in your webpack.config.js file e.g.
"externals": {
"bindings": "require('bindings')",
"ffi": "require('ffi')"
}

Resources