Select correct environment.ts in webpack - node.js

Inside my webpack.config.js, I am returning the correct webpack config file based on passed env:
module.exports = (env) => {
return require(`./webpack.${env}.js`)
};
Inside my webpack.prod.js:
module.exports = {
entry: './src/app.ts',
target: 'node',
module: {
rules: [{test: /.tsx?$/, use: 'ts-loader'}]
},
mode: 'production',
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'app.js',
}
};
Then I have inside /src/environments, two environment files:
environment.ts
environment.prod.ts
In any of my other services, I refer to environment as:
import {environment} from '../environments/environment';
Actually I got this idea from angular-cli. And I would like to also use this in node.js. My question is how do I specify in the webpack to rename environment.prod.ts and use that when building for production?

In node environment specific context is toggled with variable NODE_ENV

So this is what I did and it works as I expected. First I install file-replace-loader, then I modified the webpack as follows:
const {resolve} = require('path');
...
module: {
rules: [{
test: /.tsx?$/,
use: 'ts-loader'
},{
test: /environment\.ts?$/,
loader: 'file-replace-loader',
options: {
condition: true,
replacement: resolve('./src/environments/environment.prod.ts'),
async: true
}
}
]
...
I set the condition to true since I am modifying the webpack.prod.js.

Related

how to use `dependOn` to bundle separate application files from the main entry point?

I have a backend project that I would like to bundle using Webpack v5.
I would like to split some of the files into their own bundles and have them imported into the main entry.
The main entry has a dependOn key that contains an array of filenames that will be used by the main entry.
This is the webpack.config.json:
module.exports = {
entry: {
app: {
import: './index.ts',
dependOn: 'routes'
},
routes: ['./routes.ts']
},
output: {
filename: '[name].js',
libraryTarget: 'commonjs2',
path: path.resolve(__dirname, 'build')
},
resolve: {
extensions: ['.ts', '.js']
},
target: 'node',
externals: [
nodeExternals()
],
mode: 'production',
optimization: {
minimize: false,
},
module: {
rules: [{ test: /\.tsx?$/, loader: 'ts-loader' }]
},
plugins: [
new ContextReplacementPlugin(/any-promise/)
]
};
After running the build two files are generated (app.js & routes.js) as expected. But when running the entry point with NodeJS I get the following error: webpack_require.C does not exist.
Going through the documentation I see that their example dependOn is based on packages and not indvidual application files.
Can you add applicaton files to dependOn? Does this have something to do with module resolution?
Let me assume you have imported the routes in your app, and you want to split routes into a separate bundle instead of being included in the bundled app.js.
Here's how you could make it with SplitChunksPlugin https://webpack.js.org/plugins/split-chunks-plugin.
module.exports = {
entry: {
app: "./index"
},
target: "node",
optimization: {
splitChunks: {
cacheGroups: {
routes: {
filename: "routes.js",
test: module => {
return module.resource && module.resource.includes("routes");
},
enforce: true,
chunks: "all"
}
}
}
}
};
Webpack will output two files, app.js and routes.js.

Webpack Config to build sdk for both Node and Browser

Can someone help me in figuring out what should be the webpack sdk config to build sdk for both web and browser?
My current config looks like this
const path = require('path');
let baseConfig = {
mode: 'production',
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'sdk/js-sdk.js',
libraryTarget: 'umd',
library: 'jsSdk',
globalObject: 'this'
},
resolve: {
extensions: [ ".ts", ".js"]
},
externals: {
"request-promise-native": "request-promise-native",
"request": "request"
},
module: {
rules: [
{ test: /\.ts$/, use: 'ts-loader' }
]
}
}
module.exports = baseConfig
Which I am building using following command
"pn-dev-build": "rm -rf dist && npm version patch && webpack --mode=development && npm publish --registry http://localhost:4873",
And then if I install it in my vue-nuxt project it gives following error
fs in ./node_modules/request/lib/har.js friendly-errors 09:06:34
net in ./node_modules/forever-agent/index.js, ./node_modules/tough-cookie/lib/cookie.js and 1 other
friendly-errors 09:06:34
tls in ./node_modules/forever-agent/index.js, ./node_modules/tunnel-agent/index.js
Can someone help me in solving the above error?
Multiple entry point approach is not the best idea here because you are bundling for two different targets(node and browser) with same config
Better would be to export a array with two configuration something like this ( and in this approch you can use multiple entry point to split your browser bundle and other stuff to make your website performant )
in webpack.config.js ( use this file as Webpack config )
const webpackBrowserConfig = require("./webpack.config.browser.js");
const webpackServerConfig = require("./webpack.config.server.js");
module.exports = [webpackServerConfig, webpackBrowserConfig];
in webpack.config.browser.js
module.exports = {
target: 'web',
mode: 'production',
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
// your browser related config
},
resolve: {
extensions: [ ".ts", ".js"]
},
externals: {
"request-promise-native": "request-promise-native",
"request": "request"
},
module: {
rules: [
{ test: /\.ts$/, use: 'ts-loader' }
]
}
}
and in webpack.config.server.js
module.exports = {
target: 'node',
mode: 'production',
entry: './src/serverIndex.ts',
output: {
path: path.resolve(__dirname, 'dist')
// your server related config
},
resolve: {
extensions: [ ".ts", ".js"]
},
externals: {
"request-promise-native": "request-promise-native",
"request": "request"
},
module: {
rules: [
{ test: /\.ts$/, use: 'ts-loader' }
]
}
}
you can also create this in same file and reduce some duplication ( whichever works for you ) I showed this approach with two different file for clarity
create a file as an entry point for the server, and another for the browser.
let baseConfig = {
mode: 'production',
entry: ['browser.ts','server.ts'],
...
}
browser.ts contains all browser-specific logic, and server.ts contains all server-specific logis.

Import path is different when service is deployed to AWS lambda using serverless framework

When I deploy a serverless function to AWS I get "Cannot find module '../knexfile'". That import path works when im working using serverless-offline. However, when I deploy to AWS all the packages get included at the root level so the import path is not correct. When I change it to 'knexfile' instead of '../knexfile' it works when deployed but not when ran locally. What can I do for the path to be what it needs to be automatically?
I would like for the path to get automatically resolved when deployed to AWS or tested locally.
I used the serverless-webpack npm package to solve the problem. This ended up being my webpack.config.js file:
const path = require('path')
const slsw = require('serverless-webpack')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: slsw.lib.entries,
target: 'node',
mode: slsw.lib.webpack.isLocal ? 'development': 'production',
optimization: {
// We no not want to minimize our code.
minimize: false
},
performance: {
// Turn off size warnings for entry points
hints: false
},
devtool: 'nosources-source-map',
externals: [nodeExternals(),
{
'sqlite3': 'sqlite3',
'mariasql': 'mariasql',
'mssql': 'mssql',
'mysql': 'mysql',
'mysql2': 'mysql2',
'mssql/package.json': 'mssql/package.json',
'mssql/lib/base': 'mssql/lib/base',
'oracle': 'oracle',
'strong-oracle': 'strong-oracle',
'oracledb': 'oracledb',
'pg-native': 'pg-native',
'pg-query-stream': 'pg-query-stream',
'tedious': 'tedious'
}],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader'
}
],
}
]
},
output: {
libraryTarget: 'commonjs2',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
sourceMapFilename: '[file].map'
}
}

TypeError: <X> is not a function when using imported function after webpack

When I push my module to npm, then import it into another application, I get TypeError: <myModule> is not a function.
Is my issue actually with webpack or with the way I am declaring / using my imported function when it is bundled via webpack? or the way I am using babel-loader?
DETAILS:
When myModule's package.json has "main":"src/index.js" which is the pre-webpacked version, it works. When I change it to "main":"dist/index.js" I get the issue.
I'm trying to use it like this:
import { myModule } from '#myNPM/myModuleInNPM'
...
async function someFunction(stuff) {
const scooby = await myModule(stuff)
...
}
my webpack config:
var path = require('path')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: './src/index.js',
target: 'node',
mode: 'production',
optimization: {
// We do not want to minimize our code.
minimize: false
},
performance: {
// Turn off size warnings for entry points
hints: false
},
devtool: 'nosources-source-map',
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader'
}
]
}
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js'
}
}
I found my answer... I needed to specify my libraryTarget in my webpack config. I am now using libraryTarget: 'commonjs' an it works beautifully

Publish multiple Vuejs components in one project to npm using webpack

Im trying to publish a project to npm that contains two or more Vue components so i can import, register and use both components like this:
import Component1 from 'npm-package'
import Component2 from 'npm-package'
this is my webpack file:
const webpack = require('webpack');
const merge = require('webpack-merge');
const path = require('path');
var config = {
output: {
path: path.resolve(__dirname + '/dist/'),
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
include: __dirname,
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.css$/,
loader: 'style!less!css'
}
]
},
externals: {
moment: 'moment'
},
plugins: [
new webpack.optimize.UglifyJsPlugin( {
minimize : true,
sourceMap : false,
mangle: true,
compress: {
warnings: false
}
} )
]
};
module.exports = [
merge(config, {
entry: path.resolve(__dirname + '/src/plugin.js'),
output: {
filename: 'vue-project.min.js',
libraryTarget: 'window',
library: 'VueProject',
}
}),
merge(config, {
entry: path.resolve(__dirname + '/src/index.js'),
output: {
filename: 'vue-project.js',
libraryTarget: 'umd',
library: 'vue-project',
umdNamedDefine: true
},
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
'src': path.resolve(__dirname, '../src'),
'components': path.resolve(__dirname, '../src/components')
}
}
})
];
and this is the index.js file i'm using as the entry point for the build process
import Component1 from './components/folder1/Component1.vue'
import Component1 from './components/folder2/Component2.vue'
export default {
components: {
Component1,
Component2
}
}
The build process using npm run build works fine and i can publish the project to npm and install it using npm install. Importing and using it works fine to, but when i run my project i get the error:
failed to mount component: template or render function not defined.
All other posts o found regarding this error did not solve my problem, as none of them tried to export multiple components.
Both components work completely as intended when im publishing them in two different projects.
What am i missing here? Thanks in advance!
You don't need to export using the components property, you simply need to do:
export {
Component1,
Component2
}
You would then do:
import {Component1} from 'npm-package';
import {Component2} from 'npm-package';
or
import {Component1, Component2} from 'npm-package';
see: https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export

Resources