Webpack compile export from ts file into nothing - javascript

There is only one line in my index.ts file.
export * from "./foo"
There is only one line in foo.ts file too.
export const foo = ()=> 'bar'
I'm only using default config from "npx webpack-cli init".
Only "mode" and "output" are edited.
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/index.ts',
output:{
filename:'index.js'
},
plugins: [new webpack.ProgressPlugin()],
module: {
rules: [{
test: /\.(ts|tsx)$/,
loader: 'ts-loader',
include: [path.resolve(__dirname, 'src')],
exclude: [/node_modules/],
options:{
transpileOnly: true
}
}]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
optimization: {
minimizer: [new TerserPlugin()],
splitChunks: {
cacheGroups: {
vendors: {
priority: -10,
test: /[\\/]node_modules[\\/]/
}
},
chunks: 'async',
minChunks: 1,
minSize: 30000,
name: false
}
},
target:"web"
}
And here is my tsconfig.js
{
"compilerOptions": {
"allowSyntheticDefaultImports": false,
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"allowJs": false,
"sourceMap": true
}
}
Here is my package.json
{
"name": "npm",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"#webpack-cli/init": "^1.0.3",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"terser-webpack-plugin": "^5.0.3",
"ts-loader": "^8.0.12",
"typescript": "^4.1.2",
"webpack": "^5.10.0",
"webpack-cli": "^4.2.0"
}
}
With these when I run build
"build": "webpack"
I got an empty index.js in "dist/index.js".
What am I missing?

I think the problem is here all about to remove unused export of webpack. Keep in mind that webpack is able to do this unless the input code passed to it must be esm style as same as you've done by configured module: "es6".
In case of exporting as library, you might have to tell webpack to build as library by specifying target or even could add a name:
webpack.config.js
{
output: {
library: "yourLibName",
libraryTarget: "umd",
filename: "index.js"
},
}

Related

Webpack watch true only works on package.json, not on all files

I have my webpack watch all my files using watch: true in webpack.config.js.
I run webpack using npm run build through this code in package.json:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
Now when I use npm run build, it only compiles every time I save package.json. How do I change it so that it compiles every time I save a file in all of my folders?
Full code
package.json
{
"name": "testproj",
"version": "1.0.0",
"description": "",
"main": "code.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "Figma",
"license": "MIT",
"devDependencies": {
"#figma/plugin-typings": "*",
"#types/node": "^16.7.1",
"css-loader": "^6.2.0",
"html-webpack-inline-source-plugin": "0.0.10",
"html-webpack-plugin": "^5.3.2",
"style-loader": "^3.2.1",
"ts-loader": "^9.2.5",
"typescript": "^4.3.5",
"url-loader": "^4.1.1",
"webpack": "^5.51.1",
"webpack-cli": "^4.8.0"
},
"dependencies": {
"#types/react": "^17.0.19",
"#types/react-dom": "^17.0.9",
"figma-plugin-ds": "^1.0.1",
"react": "^17.0.2",
"react-dev-utils": "^11.0.4",
"react-dom": "^17.0.2"
}
}
webpack.config.js
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const path = require('path')
const webpack = require('webpack')
module.exports = (env, argv) => ({
watch: true,
watchOptions: {
ignored: /node_modules/,
},
mode: argv.mode === 'production' ? 'production' : 'development',
devtool: argv.mode === 'production' ? false : 'inline-source-map',
entry: {
ui: './src/ui.tsx',
code: './src/code.ts',
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.svg/,
type: 'asset/inline'
}
]
},
resolve: { extensions: ['.tsx', '.ts', '.jsx', '.js'] },
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new webpack.DefinePlugin({
'global': {}
}),
new HtmlWebpackPlugin({
inject: "body",
template: './src/ui.html',
filename: 'ui.html',
chunks: ['ui']
}),
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/ui/]),
],
})
Use the command in your package.json
webpack --watch --config webpack.config.js
To fix this, add cache: false in the HTMLWebpackPlugin object argument in webpack.config.js:
plugins: [
new webpack.DefinePlugin({
'global': {}
}),
new HtmlWebpackPlugin({
inject: "body",
template: './src/ui.html',
filename: 'ui.html',
chunks: ['ui'],
cache: false // Add this line
}),
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/ui/]),
],

Exclude in webpack-obfuscator does not work

We have implemented the obfuscator as per https://github.com/javascript-obfuscator/webpack-obfuscator.
We have only three subfolders in our project under the root: node_modules, src, dist. We expect these to all be non-obfuscated with the appropriate exclude in plugin, so the subsequent code in the bundle is not obfuscated at all. (This is, of course, just an intermediate step to make sure the exclude works at all. In the end, we just want to exclude node_modules from obfuscation).
The versions javascript-obfuscator (4.0.0) and webpack-obfuscator (3.5.1) are both the latest and should therefore be compatible?!
package.json
{
"name": "metrolyzer_npm",
"version": "1.0.0",
"description": "includes information about all modules required for the Metrolyzer",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"build": "webpack"
},
"repository": {
"type": "git",
"url": "https://git.jetbrains.space/else42/metro/metrolyzer.git"
},
"author": "",
"license": "ISC",
"dependencies": {
"autoprefixer": "^10.4.13",
"bootstrap": "5.0.2",
"css-loader": "^6.7.2",
"d3": "^7.7.0",
"dat.gui": "0.7.7",
"javascript-obfuscator": "^4.0.0",
"jquery": "3.6.0",
"postcss-loader": "^7.0.2",
"sass": "^1.56.1",
"sass-loader": "^13.2.0",
"style-loader": "^3.3.1",
"three": "0.123.0",
"three-orbit-controls": "^82.1.0",
"three.meshline": "^1.4.0",
"troika-three-text": "0.45.1",
"xlsx": "0.10.8"
},
"keywords": [],
"devDependencies": {
"webpack": "^5.75.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1",
"webpack-obfuscator": "^3.5.1"
}
}
webpack.config.js
const path = require('path');
var WebpackObfuscator = require('webpack-obfuscator');
module.exports = {
mode: 'production',
entry: {
index: './src/index.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '',
sourceMapFilename: "[name].js.map" // Allows us to get more detailed information about the source of an error
},
devtool: "source-map", // Allows us to get more detailed information about the source of an error
optimization: {
minimize: false, // Minimization should enabled for production
},
plugins: [
new WebpackObfuscator({rotateStringArray: true}, ['*node_modules*','*src*','*dist*'])
],
module: {
rules: [
{
test: /\.(sass|css)$/,
use: [ // The use of a loader is required because we are using .css from bootstrap
'style-loader',
'css-loader',
]
},
{
test: /\.js$/,
exclude: [
path.resolve(__dirname, 'node_modules')
],
enforce: 'post',
use: {
loader: WebpackObfuscator.loader,
options: {
rotateStringArray: true
}
}
}
]
}
};
Update: We were able to reproduce and resolve the problem. Two things had to be changed in order to make the exclusion of folders/files work.
Removing the line: new WebpackObfuscator({rotateStringArray: true}, ['*node_modules*','*src*','*dist*']) from the variable plugins. We suspect this to be redundant.
Use path.join() instead of path.resolve() when specifying which folders/files should be excluded. path.resolve() was resulting in C:\node_modules rather than C:\Users\ ... \ ... \ ... \node_modules\
After implementing these changes our issue was resolved. Below is the resulting webpack.config.js. Changes to the config other than the ones described in 1. and 2. can be ignored.
webpack.config.js
const path = require('path');
const WebpackObfuscator = require('webpack-obfuscator');
module.exports = {
mode: 'production',
entry: {
index: './src/index.js',
},
resolve: {
fallback: {
"stream": require.resolve("stream-browserify"),
"buffer": require.resolve("buffer")
}
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '',
sourceMapFilename: "[name].js.map"
},
devtool: "source-map",
optimization: {
//minimize: true,
module: {
rules: [
{ test: /\.(js|mjs)$/,
exclude: [
path.join(__dirname, '/node_modules/'),
path.join(__dirname, '/src/example/gui.js'),
],
enforce: 'post',
use: {
loader: WebpackObfuscator.loader,
options: {
reservedStrings: [ '\s*' ],
rotateStringArray: true,
identifierNamesGenerator: 'mangled-shuffled',
}
}
},
{ test: /\.(sass|css)$/,
use: [
'style-loader',
'css-loader',
]
}
]
}
};

Why is webpack not including my function in my ts file

I have made a fresh blazor serverside app. And I have created a tsconfig.json and JS/src folder in my project folder. In Terminal, I have used npm init -y in my JS folder. Node modules can now be installed. I installed webpack and created a webpack.config.js file in my JS folder. Then I create a simple ts file with an alert function. After configuring my tsconfig.json in my project root, I added <script src="js/bundle.js"></script> to my _Layout.cshtml. And then in my index.cshtml page I added a button and some code to call the compiled bundle.js from webpack, located in wwwroot/js/.
I cannot see the function in my bundle.js file. What have I done wrong?
Folder structure:
tsconfig.json:
{
"compilerOptions": {
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"target": "ES2017",
"moduleResolution": "Node"
},
"exclude": [
"node_modules"
],
"include": [
"./JS/src/*.ts"
]
}
webpack.config.js:
const path = require('path');
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude:/node_modules/,
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '../wwwroot/js'),
},
};
index.ts:
function showAlert() {
alert("this is a test");
}
package.json:
{
"name": "js",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"ts-loader": "^9.2.6",
"typescript": "^4.5.5",
"webpack-cli": "^4.9.2"
}
}
Ok so after some struggling I figured out that I need to expose the function as a library.
In webpack.config.js:
const path = require('path');
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude:/node_modules/,
},
],
},
resolve: {
extensions: ['', '.js', '.ts']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '../wwwroot/js'),
libraryTarget: 'umd',
library: 'EntryPoint'
},
};
Take note of the library and library target in the output section. I am not entirely sure whether var umd const or let is better for the library target, as I am not sure what UMD is. however it seems to work with either.
Here is my updated index.ts file:
import { Calculator } from "./calculator";
export function showAlert() {
console.log("Hello world");
alert("this is a test");
}
export let foo = new Calculator();
let bar = new Calculator();
Notice how foo and showAlert have export in front. This is required. Bar is not accessible.

Work with web-workers using comlink on a webpack5 project with typescript

I have a project written on Typescript and bundeled using webpack5.
I try to use web-workers to off-load some of the code from the min thread.
main.worker.ts:
import { expose } from 'comlink';
import {TimeConsumingFunction} from "./TimeConsumingFunction"
const exports = {
TimeConsumingFunction
};
export type WorkerInterfaceTimeConsumingFunction = typeof exports;
export default null as any;
expose(exports);
main.ts:
import { wrap } from 'comlink';
import {WorkerInterfaceTimeConsumingFunction, default as DataPixelsWorker} from './main.worker';
const worker = new Worker(new URL("./main.worker", import.meta.url));
const workerApi = wrap(worker);
let result = await workerApi.TimeConsumingFunction();
tsconfig:
{
"compilerOptions": {
"target": "es3",
"module": "esnext",
"lib": ["webworker", "es2018", "dom"],
"allowJs": true,
"checkJs": false,
"sourceMap": true,
"removeComments": false,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"esModuleInterop": true
},
"include": [
"./**/*"
],
"exclude": [
"./plugins/**/*",
"./typings/**/*",
"./dev/**/*",
"./dist/**/*"
]
}
webpack.js:
const path = require('path');
module.exports = [
{
entry: './main.ts',
mode: 'production',
target: ['web', 'es5'],
module:
{
rules:
[
{
test: /\.worker\.(js|ts)$/,
use: { loader: 'worker-loader' }
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve:
{
extensions: [ '.tsx', '.ts', '.js' ]
},
output:
{
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
optimization:
{
minimize: true,
},
stats:
{
colors: true
}
}
];
Package.json:
{
"name": "Project",
"sideEffects": false,
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --progress --config=./webpack.js --mode production --output-path ./dist/."
},
"devDependencies": {
"#babel/core": "^7.14.6",
"#babel/plugin-proposal-class-properties": "^7.14.5",
"#babel/plugin-proposal-decorators": "^7.14.5",
"#babel/plugin-transform-runtime": "^7.14.5",
"#babel/preset-env": "^7.14.5",
"#babel/preset-typescript": "^7.14.5",
"babel-loader": "^8.2.2",
"ts-loader": "^4.5.0",
"typescript": "^4.2.4",
"webpack": "^5.36.0",
"webpack-cli": "^4.6.0",
"webpack-version-file-plugin": "^0.4.0",
"worker-loader": "^3.0.8"
},
"dependencies": {
"#babel/runtime": "^7.14.6",
"comlink": "^4.3.1",
"core-js": "^3.11.2"
},
"keywords": [],
"author": "",
"license": "ISC"
}
When the project is transpiled using the command npm run build the output contains 2 files:
main.js
main.worker.js
The output files are uploaded to a CDN. The files will be loaded from the URL https://www.example.com/main.js.
The content is loaded from the URL https://www.example-content.com
The content contains the following script tag <script src='https://www.example.com/main.js'></script>
When the content is loaded, the following error appears on the browser's console:
main.js?x=1111:1 Uncaught (in promise) DOMException: Failed to construct 'Worker': Script at 'https://www.example.com/main.worker.js'
cannot be accessed from origin 'https://www.example-content.com'.
at e.<anonymous> (https://www.example.com/main.js?x=1111:1:313839)
Because the script is loaded from a CDN that is accessible through a different domain than the content that loads the script I think the best way is to bundle the files main.worker.js into main.js. Is there a way doing that with webpack 5?
Is there another way to overcome this problem?

Integrating Cesium/Resium with a build of npx create-react-app is not working

I'm using an "ejected" version of npx create-react-app due to my needing to add several dependencies. This has all working just fine until I need to add Cesium and Resium.
I've been following these instructions for configuring webpack, but I'm assuming there is something about the configuration that comes with "npx create-react-app" that is making the requirements slightly different.
https://resium.darwineducation.com/installation2
I've also tried craco-cesium, as instructed, but it doesn't seem to work neither - I get the same message.
So as most of you know, the webpack that comes along with the npx package for React is quite large. So I think this is where the issue lies. I've added the following to the default webpack.config.js
const cesiumSource = "../node_modules/cesium/Source"
const cesiumWorkers = "../Build/Cesium/Workers"
{
...
alias: {
'react-native': 'react-native-web',
cesium$: 'cesium/Cesium',
cesium: 'cesium/Source'
},
...
plugins: [
new CopyWebpackPlugin([
{
from: path.join(cesiumSource, cesiumWorkers),
to: "Workers",
},
{
from: path.join(cesiumSource, "Assets"),
to: "Assets",
},
{
from: path.join(cesiumSource, "Widgets"),
to: "Widgets",
},
]),
new webpack.DefinePlugin(env.stringified),
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify("/"),
}),
]
...
}
I'm getting the errors:
unable to locate '..\node_modules\cesium\Build\Cesium\Workers' at 'C:\Users\USER\Documents\viper-noms\node_modules\cesium\Build\Cesium\Workers'
unable to locate '..\node_modules\cesium\Source\Assets' at 'C:\Users\USER\Documents\viper-noms\node_modules\cesium\Source\Assets'
unable to locate '..\node_modules\cesium\Source\Widgets' at 'C:\Users\USER\Documents\viper-noms\node_modules\cesium\Source\Widgets'
Which make me think that the issue is something to do with the new webpack.DefinePlugin()
Any ideas? I'm pretty sure create-react-app changes the publicPath, but I'm not clear on how to accommodate for it.
I was unable to troubleshoot the npx create-react-app build. But I was able to step through the installation of modules manually and got it to work. For those of you that need this sort of thing, here are the config files for a stable build using React + Redux + Cesium + TypeScript.
If anyone has more insight into why I had issues please feel free to chime in. I'll switch the answer if someone can point out a way to get the create-react-app working.
package.JSON:
{
"name": "project",
"version": "0.0.1",
"private": true,
"scripts": {
"bundle": "webpack",
"type-check": "tsc --noEmit",
"type-check:watch": "npm run type-check -- --watch",
"start": "webpack-dev-server",
"test": "eslint .",
"build": "webpack --mode production"
},
"devDependencies": {
"#babel/core": "7.5.5",
"#babel/plugin-proposal-class-properties": "7.5.5",
"#babel/plugin-proposal-object-rest-spread": "7.5.5",
"#babel/preset-env": "7.5.5",
"#babel/preset-react": "7.0.0",
"#babel/preset-typescript": "7.3.3",
"babel-loader": "8.0.6",
"copy-webpack-plugin": "^5.0.3",
"css-loader": "^3.1.0",
"eslint": "^6.0.1",
"eslint-plugin-react": "^7.14.3",
"html-webpack-include-assets-plugin": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"strip-pragma-loader": "^1.0.0",
"style-loader": "^0.23.1",
"typescript": "^3.3.3",
"url-loader": "^2.0.1",
"webpack": "^4.37.0",
"webpack-cli": "^3.3.6",
"webpack-dev-server": "^3.7.2"
},
"dependencies": {
"#types/cesium": "^1.59.0",
"#types/node": "^12.7.5",
"#types/react": "^16.9.2",
"#types/react-dom": "^16.9.0",
"cesium": "^1.59.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"redux": "^4.0.4",
"resium": "^1.7.0",
"source-map-loader": "^0.2.4",
"typescript": "^3.6.3"
}
}
webpack.config.js
"use strict";
const path = require("path");
const webpack = require("webpack");
const HtmlPlugin = require("html-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const cesiumSource = "node_modules/cesium/Source";
const cesiumWorkers = "../Build/Cesium/Workers";
module.exports = (env, args) => {
const prod = args.mode === "production";
return {
context: __dirname,
devServer: {
hot: true,
port: 3000,
open: true,
},
devtool: !prod ? void 0 : "eval-source-map",
entry: ["./src/index.js"],
output: {
filename: '[name].js',
path: path.join(__dirname, "./build"),
sourcePrefix: "",
},
resolve: {
alias: {
cesium$: "cesium/Cesium",
cesium: "cesium/Source"
},
extensions: [".ts", ".tsx", ".js", ".jsx"]
},
mode: prod ? "production" : "development",
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|gif|jpg|jpeg|svg|xml|json)$/,
use: ["url-loader"],
},
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
},
...[
prod
? {
// Strip cesium pragmas
test: /\.js$/,
enforce: "pre",
include: path.resolve(__dirname, cesiumSource),
use: [
{
loader: "strip-pragma-loader",
options: {
pragmas: {
debug: false,
},
},
},
],
}
: {},
],
],
},
amd: {
toUrlUndefined: true,
},
node: {
fs: "empty",
},
plugins: [
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify("/"),
}),
new CopyPlugin([
{
from: path.join(cesiumSource, cesiumWorkers),
to: "Workers",
},
{
from: path.join(cesiumSource, "Assets"),
to: "Assets",
},
{
from: path.join(cesiumSource, "Widgets"),
to: "Widgets",
},
]),
new HtmlPlugin({ inject: true, template: path.join(path.resolve(__dirname, ''), 'index.html') }),
...(prod ? [] : [new webpack.HotModuleReplacementPlugin()]),
],
};
};
tsconfig.json
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"noFallthroughCasesInSwitch": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"moduleResolution": "node",
"esModuleInterop": true,
"noUnusedLocals": true,
"noImplicitAny": true,
"target": "es2015",
"module": "es2015",
"strict": true,
"jsx": "react"
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist"
]
}
.babelrc
{
"presets": [
"#babel/env",
"#babel/typescript",
"#babel/react"
],
"plugins": [
"#babel/proposal-class-properties",
"#babel/proposal-object-rest-spread"
]
}
The documentation has been a little bit deprecated on https://resium.darwineducation.com/installation1.
The problem is in HtmlWebpackIncludeAssetsPlugin. Instead of this plugin you need to
install html-webpack-tags-plugin. After that write its configuration on ejected webpack.config.js. My example:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const HtmlWebpackTagsPlugin = require('html-webpack-tags-plugin');
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
new HtmlWebpackTagsPlugin({ tags: ['cesium/Cesium.js', 'cesium/Widgets/widgets.css'], append: false }),
// Other plugins...
].filter(Boolean),

Categories