bundle an npm package AND convert it into an es module - javascript

I want to import chessground into a project of mine. It seems it's a CommonJS module, so i used browserify to import it into my web page.
browserify -r chessground > chessground.js
In order to use it in my webpage, I use
const Chessground = require('chessground').Chessground
but I saw in this project that they import it like
import {Chessground} from 'chessground'
I know they are douing with webpack, but for the life of me I can't figure out how to bundle an entire npm package into one file AND convert it into an ES module. Can anyone help me?

There is noway to bundle your packages without using a bundler like webpack or rollup.js.
If it is necessarily to use task runner you may find a way to make the bundler work with your task runner.
I had the same problem with gulpjs and wepack, and it was really painful to make it work. The solution was using a webpack and webpack plugins in gulpjs.
const webpack = require('webpack');
const webpackStream = require('webpack-stream');
const path = require('path');
const webapckJsConfig = {
mode: (process.env.APP_ENV === 'dev' && process.env.APP_DEBUG === 'true') ? 'development' : 'production',
devtool: (process.env.APP_ENV === 'dev' && process.env.APP_DEBUG === 'true') ? 'source-map' : false,
entry: {
// Website JS Files
'website/home.js': './resources/js/website/home.js',
'website/notfound.js': './resources/js/website/notfound.js',
'website/error.js': './resources/js/website/error.js',
// Admin JS Files
'admin/home.js': './resources/js/admin/home.js',
'admin/notfound.js': './resources/js/admin/notfound.js',
},
output: {
path: path.resolve(__dirname, 'public/'),
filename: '[name]',
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
},
},
],
},
};
// JavaScript lint Cehck ✅ Convert 🔂 Compresse 🔄 Output ↪ 📁 public/js
async function scripts() {
return gulp
.src(`${JAVASCRIPT_DIR}/**/*.js`)
.pipe(webpackStream(webapckJsConfig), webpack)
.pipe(gulp.dest(`${JS_PUBLIC_DIR}`));
}
exports.scripts = scripts;
you can also check it here
You can of course take the webpack configuration and put them in external file, but you have to consider that you will confuse other developers because they will think webpack is independent and start to use it as an independent tool, so that's why I keep it in gulp.js.

Related

Can you compile a TS file with webpack separately from Vue application?

So I have a Vue 3 + Typescript app. npm run build of course takes the app and compiles it into the dist folder so it can be deployed. I have a web worker typescript file that I would like to be compiled separately so that it ends up in the root of the dist folder with the name worker.js. Here is what I'm looking for:
dist
|- worker.js
src
|- worker.ts // This gets compiled to js file in dist folder
I tried doing this by using webpack's DefinePlugin in my vue.config.js like so:
const webpack = require('webpack')
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
entry: `${__dirname}/src/worker.ts`,
module: {
rules: [
{
test: /worker\.ts$/,
use: 'ts-loader',
exclude: /node-modules/
}
]
},
resolve: {
extensions: ['.ts']
},
output: {
filename: 'worker.js',
path: `${__dirname}/dist`
}
})
],
resolve: {
alias: {
vue$: 'vue/dist/vue.esm-bundler.js'
}
}
}
}
Unfortunately this doesn't work, npm run build just completely ignores the worker.ts file and it doesn't show up in the dist folder anywhere, not even as a chunk. Any suggestions? Or is what I'm wanting to do even possible? Thanks for any help!
I was able to get the desired result using esbuild. Now I can write my web worker in Typescript and use classes and functions from my Vue app. It also compiles lightning fast. I just added the node ./esbuild.js command to my npm run dev and npm run build scripts, and now it compiles to the public folder before the Vue app builds. Here is my esbuild.js file.
const esbuild = require('esbuild')
const { nodeExternalsPlugin } = require('esbuild-node-externals')
const config = {
entryPoints: ['./src/worker.ts'],
outfile: 'public/worker.js',
bundle: true,
minify: false,
logLevel: 'silent',
plugins: [nodeExternalsPlugin()]
}
esbuild.build(config).catch(() => process.exit(1))
Let me know if you have any questions, I'd be happy to help anyone out getting this working.

Access fs module in typescript and webpack [duplicate]

I'm using node.js and webpack to create a bundle. From what I've read, node.js should contain fs module for managing files. However when I call require("fs") I get an Cannot find module "fs" error. What should I do?
I came across this problem myself when bundling with webpack and found the answer on this thread.
The way to solve it for me was to use the following config:
module.exports = {
entry: "./app",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{
test: /\.js$/,
exclude: 'node_modules',
loader: 'babel',
query: {presets: ['es2015']},
}
]
},
target: 'node'
};
By setting target to node webpack will make the necessary changes to bundle your node application
Edit: This answer targeted webpack 1.x which has now been superseded.
If you are running your webpack bundle in nodejs environment then target: 'node' is required in webpack.config.js file otherwise webpack takes default value as web for target check here.
You can resolve the issue in two ways
Add below configuration to your webpack.config.js
node: {
fs: "empty"
}
OR
Add below configuration to your package.json
"browser": {
"fs": false
}
Edit:
promising fix is
"browser": {
"fs": false
}
I had the same issue when bundling a NWjs application using webworkers (which in turn had node enabled).
The solution I found was to include each native module I used in externals with the prefix commonjs to the name of the module. For example:
...
target: "webworker", // or 'node' or 'node-webkit'
externals:{
fs: "commonjs fs",
path: "commonjs path"
}
...
I've done the same for targets "webworker" and "node-webkit" in different projects to solve the same issue.
webpack nwjs webworker nodejs node
Add below configuration to your webpack.config.js
resolve: {
fallback: {
fs: false
}
}
I needed to build a class that would use fetch if executed in a browser, or fs if executed in node. For other reasons, it was impractical to produce separate bundles, so I produced a single browser-targeted bundle.
The solution I used was to use eval('require("fs")') if the script was running in node.
const fs = eval('require("fs")')
Browser-safe (fs is null in the browser):
const fs = typeof window === 'object'
? null
: eval('require("fs")')
After trying everything I found on the internet (target, externals, node configs), the only solution that actually worked for me was replacing:
const filesystem = require("fs")
or
import fs from "fs"
by the special webpack version
const fs = __non_webpack_require__("fs")
This generates a require function that is not parsed by webpack.
In addition to the answer of PDG
I'm used to this short copy/paste candy.
Using path and fs :
var nodeModules = {};
fs.readdirSync(path.resolve(__dirname, 'node_modules'))
.filter(x => ['.bin'].indexOf(x) === -1)
.forEach(mod => { nodeModules[mod] = `commonjs ${mod}`; });
// Before your webpack configuration
module.exports = {
...
}
Then inside your configuration file, include the nodeModules variable in the externals
...
externals: nodeModules,
...
It would be more elegant to use pre-defined solution as:
Adding target: 'node' to webpack config file.
More info on: official documentation
For the solution we are building we had to force an older version of webpack:
npm install --save --force webpack#webpack-3

Compiling or obfuscating node js

I have an existing node js backend that need to deploy on customer premise. I would like to compile/obfuscate the code before passing to client.
I do not know whether it is "compilable".
But at very least i want to have only single merged code into index.js file (other javascript file all remove) that is obfuscated before passing to client.
Is there any existing npm module that does that and how reliable that an obfuscated code work as it is then original code.
What are your company/ ways to deal with it when u need to pass an existing node js source code deployable at client premise.
I am much more looking at existing library that can automate the whole process.
eg: npx run obfuscate-code --entrypoint.js (it will search all the import/require from node js and compile everything.
Folder structure is as follow.
home
- controllers (folder)
- file1.js
- file2.js
- languages (folder)
- en.js
- services (folder)
- service1.js
- service2.js
- index.js (entry point)
You can make an executable using PKG (npm package) see => https://github.com/zeit/pkg
or webpack if you want to make a single js file that is minimized.
// webpack.config.js
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: 'production',
target: 'node',
externals: [nodeExternals()],
entry: {
'build/output': './src/index.js'
},
output: {
path: __dirname,
filename: '[name].bundle.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['env', {
'targets': {
'node': 'current'
}
}]
]
}
}
}]
}
};
By using nodeExternals you don't put external dependencies in the main js file but you refer to node_modules.
You can use both those 2 solutions using npm run ... by adding them to your scripts section in package.json

Configure Webpack 4 with aliases, Babel 7 to build React components library

I'm trying to create two React projects:
React components library (only components without working application)
SPA application which uses created components (examples application)
I would like to achieve a folders structure like:
./src - directory with React components
./example - contains SPA app which uses ./src components
There are configuration files in example directory (simplest React + webpack config without HMR and other stuff):
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const aliases = require('./aliases.js');
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
}
]
},
resolve: {
alias: aliases
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
aliases.js
var path = require('path');
module.exports = {
'webpack-alias-react': path.resolve(__dirname, '../src')
};
babel.rc
{
"presets": ["#babel/preset-env", "#babel/preset-react"]
}
VSCode alias config is in jsconfig.json file.
And there is my problem.
When ./src/SimpleComponent contains code like that:
const SimpleComponent = () => {
return 'string';
};
Running npm run build command builds working application.
But when ./src/SimpleComponent returns:
const SimpleComponent = () => {
return <div>abc</div>;
};
npm run buid command throws exception:
ERROR in ../src/SimpleComponent.js Module build failed (from
./node_modules/babel-loader/lib/index.js): SyntaxError:
D:\Tranzystor\webpack-alias-react\src\SimpleComponent.js: Unexpected
token (4:9)
How to solve this webpack/Babel configuration issue?
Why is it possible to write <div> in App.js?
Is that right approach?
Whole code is here available.
I've solved that issues with Babel 7 and extended solution for that kind of issues is there:
github
It's ready to use webpack 4 + React + Babel 7 + eslint configuration.
It can be helpful for monorepo solutions.
Publishing your own components library to npm can be another application. As I mentioned above ./src directory contains small react components (content which you want to publish on npm). In ./demo directory there is spa application which shows how to use supplied components (it can be storybook for example).

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