Typescript library build - node.js

I am new with webpack and I am currently trying to build my library which is similiar to LINQ, Java 8 Stream API #szilanor/stream for npm.
Here is my webpack.config.ts
import {Configuration} from 'webpack';
import TerserPlugin from 'terser-webpack-plugin';
import * as path from 'path';
const config: Configuration = {
mode: 'production',
devtool: 'source-map',
entry: './src/index.ts',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'build'),
library: 'Stream',
libraryTarget: 'umd',
clean: true,
},
optimization: {
minimize: true,
minimizer: [new TerserPlugin({extractComments: false})],
},
module: {
rules: [
{
test: /\.([mjt])s$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
},
},
],
},
resolve: {
extensions: ['.ts', '.js', '.json'],
},
};
export default config;
as it show I am trying to create an 'umd' bundle with babel and generate the type definitions with tsc.
So my question is that is gonna work in every situation whatever project I am trying to use it in (for example angular, react, node...)? If not can you help me to fix it?

Related

How to remove duplicated dependencies code from webpack bundle?

I have these local NPM packages:
common-package
^ ^
| |
father-package mother-package
^ ^
| |
son-package
Both father-package and mother-package import common-package, and then son-package imports both father-package and mother-package
The problem here is that the son-package bundle duplicates the common-package code. The common-package has a User.ts class and as you can see there are 2 definitions of the User.ts class in the output bundle when searching for "class User {":
My goal is to dedupe it. I believe that is possible by tweaking webpack.config.js optimization but i cant figure how.
Here is what I have tried so far:
son-package webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins:[
new HtmlWebpackPlugin({
template: './index.html',
inject: true,
filename: './index.html'
})
],
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
mode: 'development',
devtool: 'source-map',
target: 'es2017',
entry: {
index: './src/Index.ts'
},
output: {
path: `${path.resolve('dist')}`,
filename: '[name].js',
library: {
type: 'module'
},
chunkFormat: 'module'
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.(js|jsx)$/,
use: 'babel-loader',
exclude: /node_modules/
},
],
},
resolve: {
extensions: ['.js', '.ts'],
}
};
Should i add the same optimization configuration in father-package and mother-package to webpack.config.json files?
Hope to have explained my problem well. Thanks in advance.
Btw, my node version is v18.11.0 and NPM is 8.19.2 and webpack 5.

TreeShaking with RxJS 7.x and WebPack 5

I would like to treeshake rxjs in my TypeScript application that is bundled via WebPack:
rxjs#7.5.7
webpack#5.74.0
According to https://rxjs.dev/guide/installation I would have to use the ES2015 exports of rxjs, but I cannot find out how to do that.
Are you aware of an example or a link to some documentation?
My current webpack config is:
const path = require('path');
module.exports = {
entry: './src/index.ts',
devtool: 'source-map',
target: 'node16',
mode: 'production',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
This config has successfully tree shaken the rxjs#6 version (which has the module entry point) but it fails to tree shake rxjs#7 and uses the full CJS version instead.
Thanks for any pointers!
Looks like this is a viable approach:
const path = require('path');
module.exports = {
entry: './src/index.ts',
devtool: 'source-map',
target: 'node18.12',
mode: 'development',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
conditionNames: ['es2015', 'import'],
mainFields: ['es2015', 'module', 'main'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};

Do I need to add my server.js into my webpack file?

I have a node server with es6 syntax, like import statements, which it cannot recognize. I am pretty sure I would have to add that to my webpack file, but unsure on how to do that and whether it is required. My node server file is called server.js
var webpack = require('webpack');
module.exports = {
entry: {
app: './src/index.js',
vendor: './src/vendor.js'
},
output: {
path: __dirname,
publicPath: '/',
filename: '[name].js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('vendor','vendor.js', Infinity)
],
module: {
loaders: [{
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-1']
}
}]
},
resolve: {
extensions: ['', '.js', '.jsx']
},
devServer: {
historyApiFallback: true,
contentBase: './'
}
};
To use the import keyword in Node you have to transpile it so it either has to be processed by webpack if you use it or at least transpiled with a tool like Babel. See this for more info:
https://github.com/babel/babel-preset-env

Sass loader not working in webpack

I am trying to get *.scss files to be supported in my webpack configuration but I keep getting the following error when I run the webpack build command:
ERROR in ./~/css-loader!./~/sass-loader!./app/styles.scss
Module build failed: TypeError: Cannot read property 'sections' of null
at new SourceMapConsumer (/Users/sean/Development/playground/webpack.sass.test/node_modules/css-loader/node_modules/postcss/node_modules/source-map/lib/source-map/source-map-consumer.js:23:21)
at PreviousMap.consumer (/Users/sean/Development/playground/webpack.sass.test/node_modules/css-loader/node_modules/postcss/lib/previous-map.js:37:34)
at new Input (/Users/sean/Development/playground/webpack.sass.test/node_modules/css-loader/node_modules/postcss/lib/input.js:42:28)
at parse (/Users/sean/Development/playground/webpack.sass.test/node_modules/css-loader/node_modules/postcss/lib/parse.js:17:17)
at new LazyResult (/Users/sean/Development/playground/webpack.sass.test/node_modules/css-loader/node_modules/postcss/lib/lazy-result.js:54:47)
at Processor.process (/Users/sean/Development/playground/webpack.sass.test/node_modules/css-loader/node_modules/postcss/lib/processor.js:30:16)
at processCss (/Users/sean/Development/playground/webpack.sass.test/node_modules/css-loader/lib/processCss.js:168:24)
at Object.module.exports (/Users/sean/Development/playground/webpack.sass.test/node_modules/css-loader/lib/loader.js:21:15)
# ./app/styles.scss 4:14-117
I can't for the life of me figure out why. It's a very basic setup.
I have created a dropbox share with the bare minimum illustrating this:
https://www.dropbox.com/s/quobq29ngr38mhx/webpack.sass.test.zip?dl=0
Unzip this then run:
npm install
webpack
Here is my webpack.config.js file:
var path = require('path')
var webpack = require('webpack')
module.exports = {
devtool: 'eval',
entry: [
'./app'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'index.js',
publicPath: '/dist/'
},
plugins: [
new webpack.NoErrorsPlugin()
],
resolve: {
extensions: ['', '.js']
},
module: {
loaders: [{
test: /\.scss$/,
loader: 'style-loader!css-loader!sass-loader'
}]
}
}
And the index.js entry file:
require('./styles.scss');
alert('foo bar baz');
And the styles.scss file:
body {
background-color: #000;
}
It appears to follow the recommendations of the sass-loader documentation site, but I can't get it to run.
:(
Information about my environment:
node - 0.12.4
npm - 2.10.1
os - OS X Yosemite
I have managed to get another workaround working that doesn't involve editing the css-loader libraries within my npm_modules directory (as per the answer by #chriserik).
If you add '?sourceMap' to the sass loader the css loader seems to handle the output.
Here is my updated configuration:
var path = require('path')
var webpack = require('webpack')
module.exports = {
devtool: 'eval',
entry: [
'./app'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'index.js',
publicPath: '/dist/'
},
plugins: [
new webpack.NoErrorsPlugin()
],
resolve: {
extensions: ['', '.js']
},
module: {
loaders: [{
test: /\.scss$/,
loader: 'style!css!sass?sourceMap'
}]
}
}
P.S. I even expanded this test to include a compass-mixins include, and this worked too.
After having the same issue, I found this: https://github.com/webpack/css-loader/issues/84
Apparently, the solution for now is to manually modify lines 17-19 of /node_modules/css-loader/lib/loader.js with
if(map && typeof map !== "string") {
map = JSON.stringify(map);
}
This fixed the problem for me.
The problem is solved by setting source-map option to true (as seen in other answers).
But in case you find messy passing options in the query string there is an alternative;
for configuring the sass loader you can create a sassLoader property in the webpack config object:
module.exports = {
devtool: 'eval',
entry: [
'./app'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'index.js',
publicPath: '/dist/'
},
plugins: [
new webpack.NoErrorsPlugin()
],
resolve: {
extensions: ['', '.js']
},
module: {
loaders: [{
test: /\.scss$/,
loader: 'style!css!sass'
// loader: ExtractPlugin.extract('style', 'css!sass'),
}]
},
sassLoader: {
sourceMap: true
},
}

Webpack and TypeScript: Cannot resolve module 'child_process' in node.d.ts

I tried to get webpack, typescript and react.js working together via awesome-typescript-loader, but I constantly get errors.
I am using awesome typescript loader at Version 0.3.0-rc.2 and webpack 1.8.9
This is my webpack.config.js:
module.exports = {
entry: './ui/index.ts',
output: {
path: __dirname + '/build-ui',
filename: 'app.js',
publicPath: 'http://localhost:8090/assets'
},
module: {
loaders: [
{
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony'
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.scss$/,
loader: "style-loader!css-loader!sass-loader"
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=8192'
},
{
test: /\.ts$/,
loader: 'awesome-typescript-loader'
}
]
},
resolve: {
extensions: ['', '.js', '.jsx', '.ts']
}
};
When I run the webpack dev server and my index.ts looks like this:
alert('hello');
It states the following error:
ERROR in ./ui/index.ts
/Users/..../typings/node/node.d.ts:29:12
Subsequent variable declarations must have the same type. Variable 'require' must be of type 'WebpackRequire', but here has type '{ (id: string): any; resolve(id: string): string; cache: any; extensions: any; main: any; }'.
Same when I put in the reference path.
When I try to import the React.js via import React = require('react'); it states:
ERROR in ./ui/index.ts
Module build failed: Cannot resolve module 'child_process' in /..../typings/node
Required in /..../typings/node/node.d.ts
I copied the node.d.ts file from the loader repo, still no luck.
Has anybody been able to get this combination work smoothly? Or should I just use a different web packager?
I'd really would like to get it to work with webpack.
All you're missing is a key target: 'node'.
This makes sure that the environment you are targeting is Node.js and not the browser, and will therefore ignore native dependencies.
Final Config:
module.exports = {
entry: './ui/index.ts',
target: 'node',
output: {
path: __dirname + '/build-ui',
filename: 'app.js',
publicPath: 'http://localhost:8090/assets'
},
module: {
loaders: [
{
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony'
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.scss$/,
loader: "style-loader!css-loader!sass-loader"
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader?limit=8192'
},
{
test: /\.ts$/,
loader: 'awesome-typescript-loader'
}
]
},
resolve: {
extensions: ['', '.js', '.jsx', '.ts']
}
};
You could consider using a different webpack TypeScript loader. I know a few had issues with node stuff. There are also a couple starter kits that may help out.
Disclaimer: I'm the maintainer of ts-loader.
Try creating a tsconfig.json file.
For example, as you are using awesome-typescript-loader this should work:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"noEmitHelpers": true
},
"exclude": [
"node_modules"
],
"awesomeTypescriptLoaderOptions": {
"forkChecker": true
},
"compileOnSave": false,
"buildOnSave": false,
"atom": { "rewriteTsconfig": false }
}

Resources