When i try to log imported modules on browser console I get this error:
As you can see, portal has app and default but it breaks when logging because the modules have other name given by webpack. My goal is log them with the original source name for debug purposes. I think the problem is related with source maps configuration but i cant figure it out.
Below are the pseudo configuration files for explanation purposes:
tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"declaration": true,
"noImplicitAny": true,
"module": "esnext",
"target": "es2017",
"allowJs": true,
"moduleResolution": "node",
"skipLibCheck": true,
"jsx": "react",
"allowSyntheticDefaultImports": true,
"paths": {
"*": ["../../node_modules/#org/*", "../node_modules/#org/*"]
},
"baseUrl" : "./src",
"outDir": "./dist"
},
"include": [
"./src"
]
}
webpack.config
const path = require("path");
module.exports={
devtool: 'source-map',
mode: "development",
output: {
filename: "[name].js",
library: {
type: 'amd'
},
path: path.resolve( "dist"),
chunkFormat: 'array-push'
},
target: "web",
resolve: {
extensions: ['.ts', '.js','.jsx','.json', '.tsx', '.scss']
},
resolveLoader: {
modules: [
path.resolve(__dirname, '..', '..', 'dist', 'loaders'),
path.resolve('node_modules')
]
},
module:{
rules: [
{
test: /\.(ts|tsx)$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.(js|jsx)$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
externalsType: 'amd',
entry: {
index: './src/Index.ts',
},
resolve: {
alias: {
module: path.resolve(__dirname, 'src', 'module')
}
},
}
package.json
{
"name": "MyProject",
"version": "1.0.0",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"dependencies": {
"requirejs": "^2.3.6"
},
"devDependencies": {
"copy-webpack-plugin": "^11.0.0",
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.75.0",
"webpack-cli": "^4.10.0",
}
}
Hope to have explained my problem well. Thanks in advance.
When I'm trying to bundle my React project, I get the following error regarding an image I'm about to load:
Oddly enough, when I hide the error overlay, I can see in a browser that my picture has been loaded correctly, despite Webpack's complaints. I've already been carefully following other working config examples, where that problem doesn't occur, but I can't easily identify the source of the issue, what leaves me here with no idea how to approach it or where to look for a hint. I've also tried different loaders: url-loader, file-loader and image-webpack-loader, but to no avail. Maybe that's Typescript what causes these troubles?
App.tsx where I'm importing my image:
import "./app.d";
import React from "react";
import SampleImage from "./assets/images/sample-image.jpg";
const App: React.FC = () => (
<div>
<img src={SampleImage} />
</div>
);
export default App;
app.d.ts with modules declarations to allow importing assets in typescripts files:
declare module "*.jpeg";
declare module "*.jpg";
declare module "*.jpeg";
declare module "*.png";
webpack.common.ts - my main Webpack config file, where I placed both url-loader and file-loader as it is in ejected create-react-app config, but it doesn't really change anything:
import path from "path";
import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
import HtmlWebpackPlugin from "html-webpack-plugin";
import { CleanWebpackPlugin } from "clean-webpack-plugin";
module.exports = {
entry: path.resolve(__dirname, "..", "./src/index.tsx"),
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve("babel-loader"),
options: {
presets: [
"#babel/preset-env",
"#babel/preset-react",
"#babel/preset-typescript",
],
},
},
],
},
{
exclude: [
/\.html$/,
/\.(js|jsx)$/,
/\.(ts|tsx)$/,
/\.css$/,
/\.json$/,
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
],
loader: require.resolve("file-loader"),
options: {
name: "static/media/[name].[hash:8].[ext]",
},
include: path.resolve(__dirname, "..", "./src/assets"),
},
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve("url-loader"),
options: {
name: "static/media/[name].[hash:8].[ext]",
},
include: path.resolve(__dirname, "..", "./src/assets"),
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js", ".jsx"],
},
output: {
path: path.resolve(__dirname, "..", "./dist"),
filename: "bundle.js",
},
devServer: {
contentBase: path.resolve(__dirname, "..", "./dist"),
hot: true,
compress: true,
open: true,
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "React App",
template: path.resolve(__dirname, "..", "./src/index.html"),
}),
new ForkTsCheckerWebpackPlugin({
async: false,
eslint: {
files: path.resolve(__dirname, "..", "./src/**/*"),
},
}),
],
};
webpack.dev.ts
import webpack from "webpack";
import ReactRefreshWebpackPlugin from "#pmmmwh/react-refresh-webpack-plugin";
module.exports = {
mode: "development",
devtool: "eval-source-map",
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve("babel-loader"),
options: {
presets: [
"#babel/preset-env",
"#babel/preset-react",
"#babel/preset-typescript",
],
plugins: [require.resolve("react-refresh/babel")],
},
},
],
},
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new ReactRefreshWebpackPlugin({
overlay: {
sockIntegration: "wds",
},
}),
],
};
webpack.prod.ts
import webpack from "webpack";
module.exports = {
mode: "production",
devtool: "source-map",
};
webpack.config.ts
import merge from "webpack-merge";
import devConfig = require("./webpack.dev");
import prodConfig = require("./webpack.prod");
import commonConfig = require("./webpack.common");
module.exports = ({ env }: { env: "dev" | "prod" }) => {
const envConfig = env === "dev" ? devConfig : prodConfig;
return merge(commonConfig, envConfig);
};
Additionaly, my .babelrc file:
{
"presets": [
"#babel/preset-env",
"#babel/preset-react",
"#babel/preset-typescript"
],
"plugins": [
"react-refresh/babel",
[
"#babel/plugin-transform-runtime",
{
"regenerator": true
}
]
]
}
and tsconfig.json:
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"esModuleInterop": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": ["src"]
}
Scripts in package.json:
"scripts": {
"start": "webpack serve --config config/webpack.config.ts --env env=dev --hot",
"build": "webpack --config config/webpack.config.ts --env env=prod",
},
I'd be really grateful for any hint how to solve the issue.
Thanks to help received here: https://github.com/webpack/webpack/issues/12276#event-4152056913, I've managed to surpass the error overlay by changing the options passed to the ForkTsCheckerWebpackPlugin in my webpack.common.ts file.
Before:
new ForkTsCheckerWebpackPlugin({
async: false,
eslint: {
files: path.resolve(__dirname, "..", "./src/**/*"),
},
}),
Now:
new ForkTsCheckerWebpackPlugin({
async: false,
eslint: {
files: path.resolve(__dirname, "..", "./src/**/*.{ts,tsx,js,jsx}"),
},
}),
I'm facing problems while developing both frontend (Redux) and backend (Express) in Typescript. I could not make hot reload work. Here is configuration of webpack.config.js in root folder:
const webpack = require('webpack');
const path = require('path');
const { CheckerPlugin } = require('awesome-typescript-loader');
const config = {
cache: true,
mode: 'development',
entry: {
'user': ['./dist/client/User/index', 'webpack-hot-middleware/client'],
'guest': ['./dist/client/Guest/index', 'webpack-hot-middleware/client']
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new CheckerPlugin()
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/static'
},
devServer: {
contentBase: './dist',
hot: true
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.jsx']
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'awesome-typescript-loader',
exclude: /node_modules/,
include: path.join(__dirname, 'client'),
options: { cacheDirectory: true }
}
]
},
node: { fs: 'empty' }
};
module.exports = config;
And tsconfig.json:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"jsx": "react",
"esModuleInterop": true,
"outDir": "dist",
"sourceMap": true,
"baseUrl": "."
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
In src I separate two folders client and server, my npm start script is tsc && node dist/server. In server/index I declare utilization of webpack compiler like this:
import config from '../../webpack.config';
const compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));
When I start the application, webpack builds normally, but it never build hot reload when I make changes in client files. I spent a whole day but still confused and don't know how to fix it yet.
are you currently using react 17?
if so, create the following in the .env file
FAST_REFRESH=false
directory
I'm trying to run my Electon application that I'm migrating from ES6 to Typescript. With my configuration I can build dll and main successfully but get an error (SyntaxError: Unexpected token ...) when I'm trying to run.
For now project files are mix of typescript and javascript files.
I use the following dependencies (main of them are):
"#babel/core": "^7.2.2", "#babel/register": "^7.0.0" and others #babel.
"electron": "6.0.2"
"react": "^16.9.0",
"typescript": "^3.5.3",
"webpack": "^4.39.2"
Scripts for run in package.json
"build": "concurrently \"npm run build-main\" \"npm run build-renderer\"",
"build-dll": "cross-env NODE_ENV=development node --trace-warnings -r #babel/register ./node_modules/webpack/bin/webpack --config webpack.config.renderer.dev.dll.js --colors",
"build-e2e": "cross-env E2E_BUILD=true npm run build",
"build-main": "cross-env NODE_ENV=production node --trace-warnings -r #babel/register ./node_modules/webpack/bin/webpack --config webpack.config.main.prod.js --colors",
"build-renderer": "cross-env NODE_ENV=production node --trace-warnings -r #babel/register ./node_modules/webpack/bin/webpack --config webpack.config.renderer.prod.js --colors",
"electron-rebuild": "electron-rebuild --parallel --force --types prod,dev,optional --module-dir app",
"dev": "cross-env START_HOT=1 node -r #babel/register ./scripts/CheckPortInUse.js && cross-env START_HOT=1 npm run start-renderer-dev",
"start-main-dev": "cross-env HOT=1 NODE_ENV=development electron -r #babel/register ./app/main.dev.js",
"start-renderer-dev": "cross-env NODE_ENV=development node --trace-warnings -r #babel/register ./node_modules/webpack-dev-server/bin/webpack-dev-server --config webpack.config.renderer.dev.js",
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"outDir": "./dist",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"strictNullChecks": false,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"sourceMap": true,
"noImplicitAny": false,
"jsx": "react",
},
"include": [
"./app"
],
"exclude": [
"node_modules",
"**/node_modules/*",
"dist"
]
}
.babelrc
{
"presets": [
["#babel/preset-env", {
"targets": { "electron": "6.0.2" },
"corejs": "2",
"useBuiltIns": "usage"
}],
"#babel/preset-typescript",
"#babel/preset-react"
],
"plugins": [
// Stage 0
"#babel/plugin-proposal-function-bind",
// Stage 1
"#babel/plugin-proposal-export-default-from",
"#babel/plugin-proposal-logical-assignment-operators",
["#babel/plugin-proposal-optional-chaining", {
"loose": false
}],
["#babel/plugin-proposal-pipeline-operator", {
"proposal": "minimal"
}],
["#babel/plugin-proposal-nullish-coalescing-operator", {
"loose": false
}],
"#babel/plugin-proposal-do-expressions",
// Stage 2
["#babel/plugin-proposal-decorators", {
"legacy": true
}],
"#babel/plugin-proposal-function-sent",
"#babel/plugin-proposal-export-namespace-from",
"#babel/plugin-proposal-numeric-separator",
"#babel/plugin-proposal-throw-expressions",
// Stage 3
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-syntax-import-meta",
["#babel/plugin-proposal-class-properties", {
"loose": true
}],
"#babel/plugin-proposal-json-strings",
"#babel/plugin-proposal-object-rest-spread"
],
"env": {
"production": {
"plugins": [
"babel-plugin-dev-expression",
"#babel/plugin-transform-react-constant-elements",
"#babel/plugin-transform-react-inline-elements",
"babel-plugin-transform-react-remove-prop-types"
]
},
"development": {
"plugins": [
"#babel/plugin-syntax-typescript",
"react-hot-loader/babel"
]
}
}
}
webpack.config.base.js
import path from 'path';
import webpack from 'webpack';
import fs from 'fs';
import { dependencies as externals } from './app/package.json';
import { dependencies as possibleExternals } from './package.json';
export default {
externals: [
...Object.keys(externals || {}),
...Object.keys(possibleExternals ||{})
],
module: {
rules: [
{
test: /\.(js|jsx|tsx|ts)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
},
'ts-loader'
]
}
]
},
output: {
path: path.join(__dirname, 'app'),
// https://github.com/webpack/webpack/issues/1114
libraryTarget: 'commonjs2'
},
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
modules: [path.join(__dirname, 'app'), 'node_modules']
},
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'production'
}),
new webpack.NamedModulesPlugin()
]
};
webpack.config.renderer.dev.dll.js
/**
* Builds the DLL for development electron renderer process
*/
import webpack from 'webpack';
import path from 'path';
import merge from 'webpack-merge';
import baseConfig from './webpack.config.base';
import { dependencies } from './package.json';
import CheckNodeEnv from './scripts/CheckNodeEnv';
CheckNodeEnv('development');
const dist = path.resolve(process.cwd(), 'dll');
export default merge.smart(baseConfig, {
devtool: 'eval',
mode: 'development',
target: 'electron-renderer',
externals: ['fsevents', 'crypto-browserify'],
module: require('./webpack.config.renderer.dev').default.module,
entry: {
renderer: Object.keys(dependencies || {}).filter(
dependency => dependency !== 'font-awesome'
)
},
output: {
library: 'renderer',
path: dist,
filename: '[name].dev.dll.js',
libraryTarget: 'var'
},
plugins: [
new webpack.DllPlugin({
path: path.join(dist, '[name].json'),
name: '[name]'
}),
new webpack.EnvironmentPlugin({
NODE_ENV: 'development'
}),
new webpack.LoaderOptionsPlugin({
debug: true,
options: {
context: path.resolve(process.cwd(), 'app'),
output: {
path: path.resolve(process.cwd(), 'dll')
}
}
})
]
});
webpack.config.renderer.dev.js
import path from 'path';
import fs from 'fs';
import webpack from 'webpack';
import chalk from 'chalk';
import merge from 'webpack-merge';
import { spawn, execSync } from 'child_process';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import baseConfig from './webpack.config.base';
import CheckNodeEnv from './scripts/CheckNodeEnv';
CheckNodeEnv('development');
const port = process.env.PORT || 1212;
const publicPath = `http://localhost:${port}/dist`;
const dll = path.resolve(process.cwd(), 'dll');
const manifest = path.resolve(dll, 'renderer.json');
const requiredByDLLConfig = module.parent.filename.includes(
'webpack.config.renderer.dev.dll'
);
if (!requiredByDLLConfig && !(fs.existsSync(dll) && fs.existsSync(manifest))) {
execSync('npm run build-dll');
}
export default merge.smart(baseConfig, {
devtool: 'inline-source-map',
mode: 'development',
target: 'electron-renderer',
entry: [
'react-hot-loader/patch',
`webpack-dev-server/client?http://localhost:${port}/`,
'webpack/hot/only-dev-server',
path.join(__dirname, 'app/index.js')
],
output: {
publicPath: `http://localhost:${port}/dist/`,
filename: 'renderer.dev.js'
},
module: {
rules: [
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: [
'#babel/preset-env',
'#babel/preset-typescript',
'#babel/preset-react'
],
plugins: [
'#babel/plugin-transform-runtime',
["#babel/plugin-proposal-class-properties", { "loose": true }],
'react-hot-loader/babel'
]
}
}
},
{
test: /\.global\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /^((?!\.global).)*\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
importLoaders: 1,
localIdentName: '[name]__[local]__[hash:base64:5]'
}
}
]
},
// SASS support - compile all .global.scss files and pipe it to style.css
{
test: /\.global\.(scss|sass)$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader'
}
]
},
// SASS support - compile all other .scss files and pipe it to style.css
{
test: /^((?!\.global).)*\.(scss|sass)$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
importLoaders: 1,
localIdentName: '[name]__[local]__[hash:base64:5]'
}
},
{
loader: 'sass-loader'
}
]
},
// WOFF Font
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff'
}
}
},
// WOFF2 Font
{
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff'
}
}
},
// TTF Font
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream'
}
}
},
// EOT Font
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: 'file-loader'
},
// SVG Font
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml'
}
}
},
// Common Image Formats
{
test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
use: 'url-loader'
},
// All files with a ".ts" or ".tsx" extension will be handled by "awesome-typescript-loader".
{
test: /\.tsx?$/,
loader: "awesome-typescript-loader"
},
// All output ".js" files will have any sourcemaps re-processed by "source-map-loader".
{
test: /\.js$/,
enforce: "pre",
loader: "source-map-loader" }
]
},
plugins: [
requiredByDLLConfig
? null
: new webpack.DllReferencePlugin({
context: process.cwd(),
// eslint-disable-next-line global-require
manifest: require(manifest),
sourceType: 'var'
}),
new webpack.HotModuleReplacementPlugin({
multiStep: true
}),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.EnvironmentPlugin({
NODE_ENV: 'development'
}),
new webpack.LoaderOptionsPlugin({
debug: true
}),
new ExtractTextPlugin({
filename: '[name].css'
})
],
node: {
__dirname: false,
__filename: false
},
devServer: {
port,
publicPath,
compress: true,
noInfo: true,
stats: 'errors-only',
inline: true,
lazy: false,
hot: true,
headers: { 'Access-Control-Allow-Origin': '*' },
contentBase: path.join(__dirname, 'dist'),
watchOptions: {
aggregateTimeout: 300,
ignored: /node_modules/,
poll: 100
},
historyApiFallback: {
verbose: true,
disableDotRule: false
},
before() {
if (process.env.START_HOT) {
console.log('Starting Main Process...');
spawn('npm', ['run', 'start-main-dev'], {
shell: true,
env: process.env,
stdio: 'inherit'
})
.on('close', code => process.exit(code))
.on('error', spawnError => console.error(spawnError));
}
}
}
});
Error message:
SyntaxError: Unexpected token {
import { app, BrowserWindow } from 'electron';
^
at Module._compile (internal/modules/cjs/loader.js:722:23)
at Module._compile (C:\tool\node_modules\pirates\lib\index.js:99:24)
at Module._extensions..js (internal/modules/cjs/loader.js:798:10)
at Object.newLoader [as .js] (C:\tool\node_modules\pirates\lib\index.js:104:7)
at Module.load (internal/modules/cjs/loader.js:645:32)
at Function.Module._load (internal/modules/cjs/loader.js:560:12)
at loadApplicationPackage (C:\tool\node_modules\electron\dist\resources\default_app.asar\main.js:109:16)
at Object.<anonymous> (C:\tool\node_modules\electron\dist\resources\default_app.asar\main.js:155:9)
at Module._compile (internal/modules/cjs/loader.js:786:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)
Update:
As ford04 said, need to use commonjs or es2015, because electron is worked only with es2015 standard. Need to set up babel presets/plugins either in .babelrc file or webpack config as well.
tsconfig.js
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"es2015",
"es6",
],
"outDir": "./dist",
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"strictNullChecks": false,
"forceConsistentCasingInFileNames": true,
"module": "es2015",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"sourceMap": true,
"noImplicitAny": false,
"jsx": "react"
},
"include": [
"./app"
],
"exclude": [
"node_modules",
"**/node_modules/*",
"dist"
]
}
.babelrc I've replaced with babel.config.js according to electron-typescript
const developmentEnvironments = ['development', 'test'];
const developmentPlugins = [
require('react-hot-loader/babel'),
require('#babel/plugin-syntax-typescript')
];
const productionPlugins = [
require('babel-plugin-dev-expression'),
// babel-preset-react-optimize
require('#babel/plugin-transform-react-constant-elements'),
require('#babel/plugin-transform-react-inline-elements'),
require('babel-plugin-transform-react-remove-prop-types')
];
module.exports = api => {
const development = api.env(developmentEnvironments);
return {
presets: [
[
require('#babel/preset-env'),
{
targets: { electron: require('electron/package.json').version },
useBuiltIns: 'usage',
corejs: 2
}
],
require('#babel/preset-typescript'),
[require('#babel/preset-react'), { development }]
],
plugins: [
// Stage 0
require('#babel/plugin-proposal-function-bind'),
// Stage 1
require('#babel/plugin-proposal-export-default-from'),
require('#babel/plugin-proposal-logical-assignment-operators'),
[require('#babel/plugin-proposal-optional-chaining'), { loose: false }],
[
require('#babel/plugin-proposal-pipeline-operator'),
{ proposal: 'minimal' }
],
[
require('#babel/plugin-proposal-nullish-coalescing-operator'),
{ loose: false }
],
require('#babel/plugin-proposal-do-expressions'),
// Stage 2
[require('#babel/plugin-proposal-decorators'), { legacy: true }],
require('#babel/plugin-proposal-function-sent'),
require('#babel/plugin-proposal-export-namespace-from'),
require('#babel/plugin-proposal-numeric-separator'),
require('#babel/plugin-proposal-throw-expressions'),
// Stage 3
require('#babel/plugin-syntax-dynamic-import'),
require('#babel/plugin-syntax-import-meta'),
[require('#babel/plugin-proposal-class-properties'), { loose: true }],
require('#babel/plugin-proposal-json-strings'),
require('#babel/plugin-transform-runtime'),
...(development ? developmentPlugins : productionPlugins)
]
};
};
webpack.config.base.js
import path from 'path';
import webpack from 'webpack';
import fs from 'fs';
import { dependencies as externals } from './app/package.json';
export default {
externals: [
...Object.keys(externals || {})
],
module: {
rules: [
{
test: /\.(js|jsx|tsx|ts)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
},
'ts-loader'
]
}
]
},
output: {
path: path.join(__dirname, 'app'),
libraryTarget: 'commonjs2'
},
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
modules: [path.join(__dirname, 'app'), 'node_modules']
},
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'production'
}),
new webpack.NamedModulesPlugin()
]
};
Your error indicates that your build system somehow did not transpile ES modules syntax to CommonJS syntax. Electron does not support ES modules in a native way easily (some good links summarizing this: Link, Link, Link, Link), so it cannot interpret the import statement at runtime.
Your old .js files with ES modules seem to be the crux here, as you transpile .ts files to "target": "es5" according to tsconfig.json. In .babelrc, you configured #babel/preset-env like this:
[
"#babel/preset-env", {
"targets": { "electron": "6.0.2" },
"corejs": "2",
"useBuiltIns": "usage"
}
]
My guess is there is no transpilation to CommonJS, because you specified Electron 6.0.2 as target, which maps to a very decent Chromium version supporting ES modules - see the setting modules: auto and what it means for further infos.
I would further isolate your problem to the main process, as you set custom Babel settings for renderer:
webpack.config.renderer.dev.js, babel-loader:
use: {
loader: 'babel-loader',
options: {
...
}
}
Whenever you set these options, .babelrc will be completely ignored and everything from options taken during the webpack build including babel transformations. So for the renderer config, Babel should take its default options, which includes converting to CommonJS syntax, effectively eliminating import errors in the renderer process.
Solution
We have to bring Babel to transpile your main process .js files to CommonJS syntax. Easiest way is to change modules option:
[
"#babel/env", {
...
"modules": "cjs"
}
],
You could add this setting in a babel config for your main process or directly in the options of babel-loader in your main webpack config (similar to renderer webpack.config). Remember, if you do the latter, you have to add every setting from .babelrc in options. As an alternative to modules option, you could also try the #babel/plugin-transform-modules-commonjs plugin.
Puh, that was a bit longer than expected. Hope you are still awake and that it helps out. Good luck!
I'm using the ngx-magicsearch module in my project with. However, I get the following error:
Uncaught SyntaxError: Unexpected token import.
I am using the version of Angular 4.2.5, Webpack version 1.15.0 and Typescript 2.3.4
Here is my Webpack file:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
'app': './app/app.module.ts',
'vendor': './app/vendor/vendor.ts'
},
resolve: {
extensions: ['', '.ts', '.js', '.css', '.html'],
modulesDirectories: ["node_modules", "assets\\js"]
},
output: {
filename: '[name].bundle.js',
},
module: {
noParse: [/jszip.js$/],
loaders: [{
test: /\.ts$/,
loaders: [
'awesome-typescript-loader',
'angular2-router-loader'
]
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?.*$|$)/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: './app',
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: './app',
loader: 'raw'
},
{
test: /[\\\/]assets[\\\/]js[\\\/]modernizr\.min\.js$/,
loader: "imports?this=>window!exports?window.Modernizr"
}
]
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
KJUR: "jsrsasign-latest-all-min",
b64utoutf8: "base64x",
dateFormat: "dateformat",
moment: "moment"
}),
new ExtractTextPlugin('[name].bundle.css'),
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor']
})
],
devServer: {
historyApiFallback: true,
stats: 'minimal'
}
};
tsconfig.js:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noEmitHelpers": false,
"sourceMap": true,
"preserveConstEnums": true,
"alwaysStrict": true
},
"exclude": [
"node_modules"
],
"compileOnSave": false,
"buildOnSave": false
}
And the errors:
The entry point of ngx-magicsearch uses ES modules. You would need to transpile them with babel to use it. Usually the packages publish a transpiled version, although many of them now also publish a version with ES modules that can be used by bundling tools that support them. ES modules are supported out of the box, since webpack 2.
It is highly recommended to upgrade webpack. You'll have to adapt your config a little. For details have a look at the official migration guide.