I have a Vite React project that I've been working on for a while now. Previously I've been on vite 2.9.14 and #vitejs/plugin-react version 1.3.2. I decided it was a good time to upgrade to the latest versions of both.
The result of doing so is my production build (vite build) doesn't compile my TypeScript/React and SCSS code. It has my index.html, it has my publicDir resources, but then the only asset it produces is a single JS file with a tiny amount of what appears to just be setup code. None of my application code is included.
I'll add that the dev server (vite) works perfectly.
I'm trying to go to vite 4.0.4 and #vitejs/plugin-react 3.0.1. I've scoured the internet trying to understand what could be going wrong here. I can't even find any reported issues like mine.
I am staying on the older versions for now.
import path from 'path';
import react from '#vitejs/plugin-react';
import fs from 'fs';
import { defineConfig } from 'vite';
const https =
process.env.CYPRESS === 'true'
? undefined
: {
cert: fs.readFileSync(
path.join(
process.cwd(),
'dev',
'certs',
'localhost.cert.pem'
),
'utf8'
),
key: fs.readFileSync(
path.join(
process.cwd(),
'dev',
'certs',
'localhost.key.pem'
),
'utf8'
)
};
export default defineConfig({
root: path.join(process.cwd(), 'src'),
base: '/expense-tracker/',
publicDir: path.join(process.cwd(), 'public'),
envDir: path.join(process.cwd(), 'environment'),
server: {
port: 3002,
host: true,
https,
proxy: {
'/expense-tracker/api': {
target: 'https://localhost:8080',
changeOrigin: true,
secure: false,
rewrite: (path: string) =>
path.replace(/^\/expense-tracker\/api/, '')
},
'/expense-tracker/oauth2': {
target: 'https://apps-craigmiller160.ddns.net/oauth2',
changeOrigin: true,
secure: false,
rewrite: (path: string) =>
path.replace(/^\/expense-tracker\/oauth2/, '')
}
}
},
plugins: [react()],
build: {
target: 'esnext',
outDir: path.join(process.cwd(), 'build'),
emptyOutDir: true
}
});
Ok, I figured out the problem. My index.html was importing my root typescript file incorrectly. In previous vite versions, the following relative path syntax was supported:
<script type="module" src="./index.tsx"></script>
Now, it has to be written with an absolute path like this:
<script type="module" src="/index.tsx"></script>
Now everything works perfectly.
Related
I'm developing mern stack web application with react from vite.js and have a problem to deal with proxy.
my client side runs at http://localhost:3000 and server side runs at http://localhost:5000.
usually I use http-proxy-midlleware to connect my server and client like below
src/setupProxy.jsx
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app){
app.use(
createProxyMiddleware('/api', {
target: 'http://localhost:5000',
changeOrigin: true
})
)
};
However, It didn't work and still sent to localhost:3000 when I post data to server with axios. I googled it and figured out that with vite.js I need to use vite.config.js
so I set up vite.config.js like below
import { defineConfig, HttpProxy } from 'vite'
import react from '#vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
host: true,
port : 3000,
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true
}
}
},
})
and tried axios call again.
const result = await axios.post('api/users/login', dataToSubmit)
.then(res => res.data);
return result;
However, contrary to my expectation, It still sent to 3000 and I do not have a clue about what is going wrong :/
xhr.js:210 POST http://localhost:3000/api/users/login 404 (Not Found)
could you tell me how to fix it? thanks for reading, your help will be appreciated.
It's required to specify secure: false like this. Reference
export default defineConfig({
plugins: [react()],
server: {
host: true,
port : 3000,
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
secure: false
}
}
},
})
I had this problem too.
My backend runs on http://localhost:8080, while my frontend runs on http://localhost:3000.
To resolve the cross-origin issue, I used the proxy alternative, but every request was returning a 404 error.
My solution was to add the rewrite: (path) => path.replace(/^\/api/, "") function in the vite settings file.
Finally, the final result of the file was:
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
server: {
proxy: {
"/api": {
target: "http://127.0.0.1:8080",
changeOrigin: true,
secure: false,
ws: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
port: 3000,
},
plugins: [react()],
});
Your port in vite.config.js file is set to 3000. So you have to set your target in src/setupProxy.jsx to 'http://localhost:3000'.
hope it helps
The project I'm working on has Redis on port 6379 and the node server on port 5000. I'm running the server by running npm run server
My package.json script is the following:
webpack --watch --progress --config ./build/server/webpack.dev.js
I'm unable to attach a debugger when I add a configuration for Attach to Node.js/Chrome on port 5000 and click the bug icon in WebStorm.
I get invalid response from the remote host
Am I supposed to patch an --inspect option to my package JSON script?
EDIT: I passed inspect down to nodemon. I'm able to attach to the debugger now, but my breakpoints arent suspending. The webpack configs are below:
const commonWebpackConfig = require('./webpack.common')
const merge = require('webpack-merge')
const NodemonPlugin = require('nodemon-webpack-plugin')
module.exports = merge(commonWebpackConfig, {
mode: 'development',
plugins: [
new NodemonPlugin({
nodeArgs: [ '--inspect'],
script: './dist/server.js'
})
]
})
const path = require('path')
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: {
server: path.join(__dirname, '..', '..', 'server', 'app.js'),
},
output: {
path: path.join(__dirname, '..', '..', 'dist'),
publicPath: '/',
filename: '[name].js'
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},
externals: [nodeExternals()],
resolve: {
extensions: ['.js']
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
plugins: [
['#babel/plugin-proposal-class-properties', {'loose': false}]
]
}
}
}
]
}
}
I found the breakpoint mapping issue. I needed to add the following:
devtool: "eval-source-map",
EDIT:
I don't think the breakpoints are fully working for blocsk of code that has async/await though
I was able to get it to work. We were using nodemon-webpack-plugin, so I needed to pass in nodeArgs like Lena said. I passed it --inspect which by default is port 9229.
I then had to add devtools: "eval-source-map So that my breakpoints had the right mapping.
EDIT:
I don't think the breakpoints are fully working for blocsk of code that has async/await though
I have created nodejs console app and trying to minify it with webpack.
webpack.config.js I got:
const path = require('path');
module.exports = {
externals: {
fs: "require('fs')",
readline: "require('readline')",
},
entry: './index.js',
output: {
path: path.resolve(__dirname, 'bin'),
filename: 'bin.js'
},
mode: 'development'
};
Everything goes ok before I run builded app:
readline.js:189
input.on('data', ondata);
^
TypeError: input.on is not a function
at new Interface (readline.js:189:11)
at Object.createInterface (readline.js:69:10)
What should I do to prevent this error?
Somewhere I found the solution. In the webpack configuration file I must set target: node to point the collector what to do with standard external packages (e.g. readline, fs, path, etc.).
I'm trying to update my app node backend to typescript and I keep hitting this syntax error:
/Users/Shared/website/src/server.ts:1
(function (exports, require, module, __filename, __dirname) { import *
as express from 'express';
^
SyntaxError: Unexpected token *
I have my tsconfig/webpack/server, etc set up as follows:
server.ts
import * as express from 'express';
import * as path from 'path';
const app = express();
const port = process.env.PORT || 3000;
app.use(express.static(path.join(__dirname, 'dist')));
app.get('*', function(req, res, next){
res.sendFile(path.resolve(__dirname, '/public', 'index.html'));
});
app.listen(port, () => console.log(`Listening on port ${port}!`));
webpack.config.json:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const outputDirectory = 'dist';
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: path.join(__dirname, outputDirectory)
},
mode: 'development',
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "ts-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
}
]
},
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
},
plugins: [
new CleanWebpackPlugin([outputDirectory]),
new HtmlWebpackPlugin({
template: './public/index.html',
favicon: './public/favicon.gif'
}),
new CopyWebpackPlugin([
{ from: 'public' }
])
]
};
tsconfig.json:
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": false,
"module": "commonjs",
"target": "es6",
"jsx": "react"
},
"include": [
"./src/**/*"
],
}
The build process succeeds, but I hit the syntaxError on run. I have a react front end also set up using typescript / tsx and it works just fine. I seem to just be running into issues with the server.ts / node files. I'm very new to trying to get this all set up, but I wanted practice making a site with numerous technologies (react/node/typescript/sass/webpack/etc). So far I have everything except the typescript/node relationship.
I had the same problem, after I realised that the tsconfig wasn't applied.
If
"module": "commonjs"
was in effect, you wouldn't have this error.
I faced the same problem before. I solve it by changing the import 'call':
From:
import * as express from 'express';
To:
const express = require('express');
As others have stated, the problem is that your tsconfig.json is not applied to server.ts. You have left out important details of your setup which is why others cannot duplicate this problem.
I have a good guess at what the issue is and having struggled with this identical problem myself, I will explain my guess here in the hope of helping some other poor soul being tormented by this issue.
The basic problem is that your server code is in a different tree than your react code. This is why the tsconfig.json is not being applied to it since (I believe) it is outside the "./src/" path specified. (Perhaps "./website/src/").
You haven't shown us the package.json file but very likely the server entry is something like "server": "ts-node ./website/src/server.ts"
To verify that the tsconfig.json application is the issue try this from the command line...
$ ts-node -O '{\"module\":\"commonjs\"}' ./website/src/server.ts
Chances are, things will start working. Now the solution is probably as simple as adding another path your tsconfig.json includes.
So I came across this post on github where basically there are two sort of working methods presented since you’re using a bundling tool targeted to es6 add
"allowSyntheticDefaultImports": true to ”compilerOptions”
Or change
import express from "express";
to
import express = require('express');
This might be happening if your tsconfig.json isn't at the root of your project. Configure webpack to point to your target config file (which you can alter with variables to point to dev and prod configurations).
https://github.com/TypeStrong/ts-loader
If set, will parse the TypeScript configuration file with given absolute path as base path. Per default the directory of the configuration file is used as base path. Relative paths in the configuration file are resolved with respect to the base path when parsed. Option context allows to set option configFile to a path other than the project root (e.g. a NPM package), while the base path for ts-loader can remain the project root.
Try modifying your webpack.config.js file to have this:
module.exports = {
...
module: {
rules: [
{
options: {
configFile: path.join(__dirname, "tsconfig.json")
}
}
]
}
};
I am trying to set up my first project using Webpack and Express but somehow I am doing something wrong.
This is what I did:
1. CREATED SAMPLE PROJECT
Created a sample project using express-generator. My folder structure is something like:
express-project
-app.js
-webpack.config.js
-public
-javascripts
-modules
-build
2. SET UP HANDLEBARS
Set up handlebars as view/template engine and created a couple of routes
3. WEBPACK CODE
Created the Webpack specific code/configuration as follows
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var webpackHotMiddleware = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&overlay=false';
module.exports = {
resolve: {
alias: {
handlebars: path.resolve('public/vendor/handlebars-v4.0.5.js'),
bootstrap: path.resolve('public/vendor/bootstrap/js/bootstrap.js'),
pubsub: path.resolve('public/vendor/ba-tiny-pubsub.js')
}
},
context: path.resolve('public/javascripts'),
entry: {
cart: ['./modules/cart', webpackHotMiddleware],
index: ['./modules/products.js', webpackHotMiddleware],
vendor: ['bootstrap', 'pubsub', webpackHotMiddleware]
},
output: {
path: path.resolve('public/javascripts/build'),
publicPath: 'javascripts/build/',
filename: '[name].js',
chunkFilename: "[id].js"
},
module: {
loaders: [
// some loaders here
]
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
}
app.js
// some code before
var app = express();
(function() {
// Step 1: Create & configure a webpack compiler
var webpack = require('webpack');
var webpackConfig = require(process.env.WEBPACK_CONFIG ? process.env.WEBPACK_CONFIG : './webpack.config');
var compiler = webpack(webpackConfig);
// Step 2: Attach the dev middleware to the compiler & the server
app.use(require("webpack-dev-middleware")(compiler, {
noInfo: false,
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true
}
}));
// Step 3: Attach the hot middleware to the compiler & the server
app.use(require("webpack-hot-middleware")(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10 * 1000
}));
})();
// some code after
4. JS CODE ON TEMPLATE
Then on the handlebars page I require the bundled javascripts
<script src="javascripts/build/common.js"></script>
<script src="javascripts/build/vendor.js"></script>
<script src="javascripts/build/cart.js"></script>
5. NPM START
Finally if I start the server using the standard npm start I see in the shell that webpack bundles everything with no errors but if I go to localhost:3000/ it does not find any of the assets created by Webpack. Instead if I run webpack to create the various bundles as if I were on production, everything is created correctly and it works as expected.
Hope someone can figure out what I am doing wrong.
Thanks
I managed to figure out what was causing the problem, by adding a slash in these 2 lines everything started to work properly:
context: path.resolve('public/javascripts/'),
path: path.resolve('public/javascripts/build/'),