The AWS compilation errors from within node_modules are occurring the build
ERROR in ../../../node_modules/#aws-sdk/client-dynamodb/models/models_0.ts 6321:51-59
TS2339: Property '$unknown' does not exist on type 'never'.
6319 | if (obj.NULL !== undefined) return { NULL: obj.NULL };
6320 | if (obj.BOOL !== undefined) return { BOOL: obj.BOOL };
> 6321 | if (obj.$unknown !== undefined) return { [obj.$unknown[0]]: "UNKNOWN" };
| ^^^^^^^^
6322 | };
6323 | }
6324 |
webpack compiled with 9 errors in 6844 ms
I have just updated AWS
"#aws-sdk/client-dynamodb": "^3.51.0",
"#aws-sdk/lib-dynamodb": "^3.51.0",
"#aws-sdk/util-dynamodb": "^3.51.0",
With webpack
const path = require('path');
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
/*
This line is only required if you are specifying `TS_NODE_PROJECT` for whatever
reason.
*/
// delete process.env.TS_NODE_PROJECT;
module.exports = {
context: __dirname,
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
entry: slsw.lib.entries,
devtool: slsw.lib.webpack.isLocal ? 'eval-cheap-module-source-map' : 'source-map',
resolve: {
extensions: ['.mjs', '.json', '.ts'],
symlinks: false,
cacheWithContext: false,
plugins: [
new TsconfigPathsPlugin({
configFile: './tsconfig.paths.json',
}),
],
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
target: 'node',
externals: [nodeExternals()],
module: {
rules: [
{
// Include ts, tsx, js, and jsx files.
test: /\.(ts|js)x?$/,
exclude: [
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, '.serverless'),
path.resolve(__dirname, '.webpack'),
],
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
}
},
'babel-loader'
]
}
]
},
plugins: [new ForkTsCheckerWebpackPlugin()],
};
And ts-config
{
"extends": "./tsconfig.paths.json",
"compilerOptions": {
"lib": ["ESNext"],
"moduleResolution": "node",
"esModuleInterop": true,
"noUnusedParameters": false,
"noUnusedLocals": false,
"resolveJsonModule": true,
"removeComments": true,
"sourceMap": true,
"target": "ES2020",
"outDir": "lib",
"paths": {
"#functions/*": ["src/functions/*"],
"#libs/*": ["src/libs/*"],
"#api/*": ["src/api/*"],
"~/*": [
"./*"
]
},
"types": [
"#types/node",
"#types/jest"
]
},
"include": ["src/**/*.ts", "serverless.ts"],
"exclude": [
"util/**/*",
"node_modules/**/*",
".serverless/**/*",
".webpack/**/*",
"_warmup/**/*",
".vscode/**/*" ],
"ts-node": {
"require": ["tsconfig-paths/register"]
}
}
Webpack looks to be still compiling node_modules regardless of it being in the excluded list.
Stop typescript type lookup traversing parent nodes
Incompatible types found by going up directories
Alter tsconfig.json to include typeRoots as a parameter as per Prevent require(...) from looking up modules in the parent directory
{
"extends": "./tsconfig.paths.json",
"compilerOptions": {
"lib": ["ESNext"],
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"module": "commonjs",
"esModuleInterop": true,
"noUnusedParameters": false,
"noUnusedLocals": false,
"resolveJsonModule": true,
"removeComments": true,
"sourceMap": true,
"target": "ES2020",
"outDir": "lib",
"paths": {
"#functions/*": ["src/functions/*"],
"#libs/*": ["src/libs/*"],
"#api/*": ["src/api/*"],
"~/*": [
"./*"
]
},
"typeRoots": [
"./"
],
"types": [
"#types/node",
"#types/jest"
]
},
"include": ["src/**/*.ts", "serverless.ts"],
"exclude": [
"util/**/*",
"node_modules",
"node_modules/**/*",
".serverless/**/*",
".webpack/**/*",
"_warmup/**/*",
".vscode/**/*"
],
"ts-node": {
"require": ["tsconfig-paths/register"]
}
}
Related
I know this has been asked before but I cannot get any accepted answer to work.
My objective is to get each of my entry points to bundle as a single [entry].js for portability. Ideally I would like to have [entry].js and [entry].[modules/vendor].js but not necessary.
What I have tried:
Using webpack-node-externals with allowlist. Results in deep modules not being found
Manual externals options path: "commonjs path". Does not change result
const {} = require('path') instead of import {} from 'path'. Also doesn't change anything
The configs below which I believe gets the closest result which is just that it cannot find built-ins.
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"esModuleInterop": true,
"outDir": "launch",
"noImplicitAny": false,
"target": "es5",
"allowJs": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
},
"exclude": [
"__tests__",
"dist",
"launch"
],
"include": [
"src/Auth",
"src/Gate",
"src/Patch",
"src/Account",
"src/Proxy",
]
}
webpack.config.js
const path = require('path');
module.exports = {
target: 'node',
mode: 'production',
entry: {
'gate': './src/Gate/index.ts',
'patch': './src/Patch/index.ts',
'auth': './src/Auth/index.ts',
'account': './src/Account/index.ts',
'proxy': './src/Proxy/index.ts',
},
stats: {warnings:false},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
optimization: {
usedExports: true,
chunkIds: 'natural',
splitChunks: {
// default splitChunks config
chunks: 'async',
minSize: 20000,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
}
}
};
I found the problem, it was the package cli that has its own type of managed module resolution that breaks with webpack. I have replaced it with commander.
when trying to run the lambda function I get the error "out/get-user-messages.handler is undefined or not exported". downloading the zip I see the "out" folder in the root and get-user-messages.js inside though. and I am exporting the handler
get-user-messages.ts
import "reflect-metadata";
import { APIGatewayEvent, APIGatewayEventRequestContext, APIGatewayProxyEvent } from "aws-lambda";
export const handler = async (event: APIGatewayProxyEvent, context: APIGatewayEventRequestContext) => {
/** Code **/
}
tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"module": "es2015",
"target": "esnext",
"noImplicitAny": false,
"outDir": "./out",
"strict": false,
"resolveJsonModule": true,
"strictNullChecks": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"esModuleInterop": true,
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.spec.ts", "**/*.test.ts"],
"paths": {
"#/*": ["src/*"]
}
}
webpack.config.js
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
var path = require('path');
/** #type {import('webpack').Configuration} */
module.exports = {
mode: "production",
module: {
mode: "production",
rules: [
{
test: /\.js|.ts|.tsx/,
exclude: /node_modules/,
use: 'babel-loader'
},
],
},
resolve: {
extensions: ['*', '.js', '.jsx', '.tsx', '.ts', '.json'],
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: ["babel-loader"]
}
]
},
plugins: [new ForkTsCheckerWebpackPlugin()],
externals: ['aws-sdk'], //avoid un-needed modules since aws-sdk exists in aws lambdas already
entry: {
//list of compiled files
"get-user-messages": path.join(__dirname, "./src/lambda/get-user-messages.ts"),
"insert-user-message": path.join(__dirname, "./src/lambda/insert-user-message.ts"),
"mark-read-user-message": path.join(__dirname, "./src/lambda/mark-read-user-message.ts"),
"get-application-release-notes": path.join(__dirname, "./src/lambda/get-application-release-notes.ts"),
"insert-application-release-note": path.join(__dirname, "./src/lambda/insert-application-release-note.ts")
},
target: 'node',
output: {
path: path.join(__dirname, "./out"),
filename: "[name].js",
library: "[name]",
libraryTarget: 'commonjs'
}
};
.babelrc
{
"presets": [
["#babel/preset-env",{"targets":{"node":"14"}, "modules":false}],
"#babel/preset-typescript"
],
"sourceType": "unambiguous",
"plugins": [
"babel-plugin-transform-typescript-metadata",
["#babel/plugin-proposal-decorators", { "legacy": true }],
"#babel/plugin-proposal-class-properties",
"#babel/plugin-transform-runtime"
]
}
the issue was the "library" option in the output section of webpack.config.js, removing that allowed me to successfully run the lambda function
I am trying to use imagemin node package in my project. It is a es6 module and I am getting error while using it.
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module. with "type" as "module" in package.json
ReferenceError: require is not defined with "type" as "commonjs" in package.json
My webpack config:
export default env => {
return {
mode: env.production ? 'production' : 'development',
entry: {
main: './src/main.ts',
worker: './src/worker.ts'
},
target: ['node', 'es2019'],
devtool: env.production ? false : 'inline-source-map',
watch: !env.production,
resolve: {
extensions: ['.ts', '.js'],
alias: {
src: _resolve(process.cwd(), './src')
}
},
module: {
rules: [{
test: /\.ts$/,
include: _resolve(process.cwd(), "src"),
use: 'ts-loader',
exclude: [/node_modules/, /\.spec\.ts/, /\.e2e-spec\.ts/]
}],
},
externalsPresets: { node: true },
externals: [nodeExternals()],
output: {
filename: '[name].js',
path: OUTPUT_DIR,
clean: !!env.production,
devtoolModuleFilenameTemplate: 'file:///[absolute-resource-path]',
library: {
type: 'module'
}
},
optimization: {
minimize: false, //!!env.production
mangleExports: true,
minimizer: [new terserPlugin({
terserOptions: {
output: {
comments: false
},
keep_classnames: true,
},
extractComments: false,
})]
},
experiments: {
outputModule: true
}
};
};
My tsconfig:
{
"compilerOptions": {
"module": "ES2020",
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2019",
"sourceMap": true,
"strict": true,
"baseUrl": ".",
"esModuleInterop": true,
"noImplicitAny": true,
"moduleResolution": "node",
"outDir": "../bin/server",
"typeRoots": [
"node_module/#types",
"./typings"
],
"types": [
"node",
"#types/jest"
]
},
"exclude": [
"node_modules"
]
}
When I try to "import" imagemin in one of my .ts file, webpack convert it to "require". I have also tried using import() but it doesn't work either.
I have made a repo on github
Is there a way to get es6 bundle (preferred) or use imagemin with commonjs bundle?
I couldn't found a way to bundle es6 format through webpack but i was able to use es6 module in commonjs system while bundling through webpack.
externals: [
nodeExternals({
allowlist: ['imagemin', 'imagemin-mozjpeg']
}),
async function ({ request }) {
if (request === 'imagemin' || request === 'imagemin-mozjpeg')
return `import ${request}`;
},
]
This is how i got imagemin to work.
Change your start script
"start": "node --experimental-modules src/index.mjs "
and In package.json Add
{
...
"type": "module",
...
}
I have a problem with Typescript not reading my return type correctly.
I am defining a function with a return type of something | null. And what typescript does is to read only the something type ignoring the null, which can be returned, when I call the function.
function nullornot(): null | string { // here is says it returns null | string
return null
}
const response = nullornot() // but here is says it returns string
My tsconfig.json file
{
"extends": "./tsconfig.paths.json",
"compilerOptions": {
"typeRoots": ["node_modules/#types", "src/#types"],
"allowSyntheticDefaultImports": true,
"lib": ["ESNext"],
"moduleResolution": "node",
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": true,
"sourceMap": true,
"target": "ESNext",
"outDir": "lib"
},
"files": ["src/#types/graphql.d.ts"],
"include": ["src/**/*.ts"],
"exclude": [
"node_modules/**/*",
".serverless/**/*",
".webpack/**/*",
"_warmup/**/*",
".vscode/**/*"
]
}
My webpack.config.js file
module.exports = {
context: __dirname,
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
entry: slsw.lib.entries,
devtool: slsw.lib.webpack.isLocal ? 'eval-cheap-module-source-map' : 'source-map',
resolve: {
extensions: ['.mjs', '.json', '.ts'],
symlinks: false,
cacheWithContext: false,
plugins: [
new TsconfigPathsPlugin({
configFile: './tsconfig.paths.json',
}),
],
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
optimization: {
concatenateModules: false,
},
target: 'node',
externals: [nodeExternals()],
module: {
rules: [
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{
test: /\.(tsx?)$/,
loader: 'ts-loader',
exclude: [
[
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, '.serverless'),
path.resolve(__dirname, '.webpack'),
],
],
options: {
transpileOnly: true,
experimentalWatchApi: true,
},
},
{
test: /\.graphql?$/,
use: [
{
loader: 'webpack-graphql-loader',
options: {
// validate: true,
// schema: "./src/schema.graphql",
// removeUnusedFragments: true
// etc. See "Loader Options" below
}
}
]
}
],
},
plugins: [],
};
Thanks for all help!
To type the result as string | null, you need to enable strictNullChecks in compilerOptions like this:
"compilerOptions": {
"strictNullChecks": true
}
See the TypeScript docs for more details.
It's because you don't have the strictNullChecks flag set to true in the tsconfig. Therefore TS won't enforce null checks, so for all intents and purposes it's just a string.
See how in this playground link where strict null checks are off it behaves the same as you're seeing, but once you turn it on the type of response is string | null
If this is a new project I'd recommend activating the strictest settings for the best type safety.
I am trying to write both frontend (React) and backend (Express) in TypeScript. At the moment, my webpack.config.js in the root folder encounters an error even though I have ts-loader for it.
This is webpack.config.js
const webpack = require('webpack');
const path = require('path');
const config = {
cache: true,
mode: 'development',
entry: {
'user': ['./src/client/User/index.tsx', 'webpack-hot-middleware/client']
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/static'
},
devServer: {
contentBase: './dist',
hot: true
},
plugins: [new webpack.HotModuleReplacementPlugin()],
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
include: path.join(__dirname, 'client')
}
]
},
node: { fs: 'empty' }
};
module.exports = config;
And this is my tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"jsx": "react",
"esModuleInterop": true,
"outDir": "dist",
"sourceMap": true,
"baseUrl": "."
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
I got the error like this:
ERROR in ./src/client/User/index.tsx 10:1
Module parse failed: Unexpected token (10:1)
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
|
| const rootComponent = (
> <Provider store={store}>
| <BrowserRouter>
| <div id="page-container" className="sidebar-o sidebar-dark enable-page-overlay side-scroll page-header-fixed side-trans-enabled">
# multi ./src/client/User/index.tsx webpack-hot-middleware/client user[0]
Thanks to FunkeyFlo answer, I found out the answer myself. I have to change both:
tsconfig.json: include also src/**/*.tsx
webpack.config.js: entry to ./dist/src/client/User/index
change include section in tsconfig to the following
{
...
"include": [
"src/**/*.ts",
"src/**/*.tsx"
],
...
}