I'm in the nightmare process of updating one of my older projects from Webpack 3 to 4 and it's introducing a whole chain of things that need fixing. The most annoying one thus far is definitely switching from webpack-dev-server to webpack-serve due to it's lack of an actual example. So with that in mind, how the heck do I use it?
Using Webpack 4.14.0 and Webpack-Serve 1.0.4.
My webpack.config.js had the following options for webpack-dev-server:
devServer: {
contentBase: path.join(__dirname, 'public'),
historyApiFallback: true,
publicPath: '/dist/'
}
I don't see options for history or public paths just yet, so I suppose I only need the content config option.
So according to the docs I'm supposed to do:
serve({
content: path.join(__dirname, 'public')
});
But where do I put this? The Github README claims that the most commonly used is to put it webpack.config.js but that seems false because the example also does this:
const serve = require('webpack-serve');
const config = require('./webpack.config.js');
serve({ config });
Do I really import a config file into itself?
I'd appreciate an example. Thanks.
I answered in another question very similar on "how to set up webpack-serve".
For simplicity, I also uploaded the full example to Github
Related
I just initiated CRA npx create-react-app my-app --template typescript and I want to make an alias when calling components, like:
import components from '#components'
where the components is located at src/components.
I've tried to config in tsconfig.json by adding:
{
"compilerOptions": {
...
"baseUrl": "./src",
"paths": {
"#utils/": ["./utils/"],
"#utils/*": ["./utils/*"]
}
}
}
Also in webpack.config.js by adding:
// const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin')
const path = require('path')
module.exports = {
resolve: {
// plugins: [new TsconfigPathsPlugin()],
alias: {
'#utils': path.resolve(__dirname, './src/utils/'),
'#utils/*': path.resolve(__dirname, './src/utils/*')
}
}
}
But it's still doesn't work.
Anyone could help me to solving these problem? But, I don't wont to use other libraries like #craco/craco.
The issue is that CRA uses its own Webpack config under the hood. Simply making a new webpack.config file doesn't actually point CRA to it, unless you run npm run eject.
Doing so is irreversible, but will add the config files to your project. From there, you should be able to modify your build settings to fit your needs.
Reminder that this cannot be undone in your project, barring perhaps a git reset, and may be more than you bargained for.
This issue with aliases seems to be a known one. Something people deemed possible earlier seems to no longer be working, or supported. Some people are speculating this could have something to do with the recent update of Webpack to version 5. And while some people claim that craco doesn't work for them, I was able to get it to work in a brand new CRA app with minimal changes. I know you're not interested in that so I won't post it here.
Alternatively, CRA allows the use of absolute imports via the src baseUrl. This will point both VSCode and Webpack to your final files, but you won't be able to set up custom paths.
"baseUrl" : "."
Using multiple index.ts files and exporting nested code up to the highest level in the directory, I'm able to keep the import paths as short as an alias:
import { persistor, store } from "src/state-management";
This could be good enough for you. If not, consider adding a package to override some of CRA's Webpack settings, or ejecting and taking matters into your own hands.
I have created a simple new Rails 7 project from scratch with Esbuild and React to get to know these, and they indeed feel like a step up from Webpack, except I can't manage to have my static files (ie image) served in production.
I have an Esbuild config file:
// esbuild.config.js
const path = require('path');
require("esbuild").build({
entryPoints: ["application.jsx"],
bundle: true,
outdir: path.join(process.cwd(), "app/assets/builds"),
absWorkingDir: path.join(process.cwd(), "app/javascript"),
publicPath: "assets",
sourcemap: true,
watch: process.argv.includes('--watch'),
plugins: [],
loader: {
'.js': 'jsx',
'.jpg': 'file',
'.png': 'file',
'.MOV': 'file'
},
}).catch(() => process.exit(1));
I store my images in the app/javascript/images/ folder, and import and use them in a React component like that (for example):
import MyImage from "./images/myimage.jpg"
import styled from "styled-components";
//...
const SomeStyledComponent = styled.div`
background-image: url(${MyImage});
`
In development, everything works fine, Esbuild copies the images in the app/assets/builds/ folder, fingerprints them, and prepends all the images url with the publicPath property of my Esbuild config. The above image for example then has the relative url assets/myimage-FINGERPRINT.jpg which is served correctly in development.
Then things get complicated in production (production here being just a Docker container built for production - I don't add the Dockerfile to keep things simple as I don't think it would help, but happy to provide it of course).
In my production.rb I have added the following:
config.public_file_server.enabled = true
(which will be replaced by an environment variable later)
The assets precompiling succeeds, and my images are in the app/public/assets/ folder, fingerprinted once more by Sprockets this time (from what I understand), but now I get 404. I have tried changing Esbuild publicPath and have tried to get the images directly in my browser, but whatever I try (assets, public, public/assets), nothing work and I am running out of ideas.
I have temporary fix which is to change the loader for images to dataurl, but that does not feel like a good practice, as my compiled javascript is going to explode.
Thank you for your help!
I ran into a similar issue, and by looking at the answers to https://github.com/rails/jsbundling-rails/issues/76 and this PR: https://github.com/rails/sprockets/pull/726/files
I was able to figure out the proper setup that works.
in the build options, I changed
publicPath: "assets",
to
publicPath: "/assets",
(included the leading /, which was missing before and causing the wrong path to be used)
and then added the following option
assetNames: "[name]-[hash].digested",
which, as you might be able to tell from the linked PR, would prevent Sprockets from adding an additional layer of fingerprinting.
I hope that helps.
when I use cra create a react app and npm run start, I see the dom tree like beblow
but for some special reason I hope it should be like
does anybody know how to change the webpackDevServer.config.js to achieve my goal?
change publicPath doesn't work o(╥﹏╥)o
Have you tried already to modify the base-href value in your index.html?
<base href="./">
With this, it will take the files from whatever server or directory you run your app from.
Also, if you need it set to that always, you could try:
<base href="http://localhost:3000/">
You could achieve that by using output property in your webpack.config.js file.
You can do something like this,
const BUILD_DIR = path.resolve(__dirname, 'point_to_static_folder')
output: {
path: BUILD_DIR,
filename: 'bundle.js',
publicPath: "http://localhost:3000/static/",
}
For your other files you can define rules to have those files as well.
I'm reading tutorial about Webpack on this: Github Webpack tutorial In this, there is a section about config webpack for production and development.
Here is development configuration:
// webpack.config.dev.js
module.exports = {
devtool: 'cheap-eval-source-map',
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index'
],
Here is production configuration:
// webpack.config.prod.js
module.exports = {
devtool: 'source-map',
entry: ['./src/index'],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
I understand the difference in option of devtool. The thing I don't understand about entry. Why in production, entry is only about src/index but in development configuration, entry also includes webpack-dev-server
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index'
The lines 'webpack-dev-server/client?http://localhost:8080' and 'webpack/hot/dev-server' are configuring/defining which port to attach an active websocket to, in this case localhost:8080, and the content base which in this case is folder/path /client. In a production environment you would never run webpack-dev-server as your bundled client assets (bundle.js or similar) would be served by a server (IIS, Node, etc), that is why there are no webpack related items in entry of the production configuration.
The Webpack plugin in question webpack-dev-server is not required to run Webpack and compile your JS sources, it simply is a tool that can be used during the development process to watch for changes and reload changes.
Technically the entry array property in development could simply be the './src/index', but then it wouldn't enable the webpack-dev-server and/or it's hot module reloading. If you wanted to run webpack-dev-server without these configuration items then you'd then need to add command line arguments when starting webpack to specify the port and/or content base.
Hopefully that helps!
Here is the 2 things you should know before understanding:
As your linked in Webpack the confusing part, there are 3 types of entry: String Array and Object. As above code, that is array type. Meaning of entry array is: Webpack will merged all those javascript files in array together. This is often unnecessary because Webpack is intelligent enough to know which javascript files need to merge while processing. You often need to do this to enhance some features from different javascript files that you don't include somewhere else in your code.
This is "little tricky" part. You see webpack/hot/dev-serverand webpack-dev-server/client?http://localhost:8080 look like a web url rather than some javascript files, right? If you check your project directory, you see there are those files: your_app_directory/node_modules/webpack/hot/dev-server.js and your_app_directory/node_modules/webpack-dev-server/client.js. And that is the real meaning: you are importing two javascript files from two modules webpack-dev-server and webpack.
Back again to your webpack configuration:
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
'./src/index'
],
That means we will merge three different javascript files together as point 2 I have figured out. As I explain in point 1, you will do this for enhancing some features. You include file webpack-dev-server/client.js for making a server for serving your code. You include file webpack/hot/dev-server.js for allowing your code autoloading. This is super useful when you in development mode without start/stop server each time you modify your code.
I've created a Github repo that has all the source code related to this question. I'm able to load build/index.html in the browser after running npm install. However, when I view the sources tab in Chrome, I don't see the source maps associated with the .tsx files.
Here's a screenshot of what I see:
I've added sourceMap: true in my tsconfig.json as well as debug: true and devtool: "source-map" in my webpack.config.json. Any thoughts on what I'm missing here?
EDIT:
This might be a silly question, but do you have to use webpack-dev-server in order to see the sourcemaps?
Your tsconfig.json might be well.
Try in your webpack.config.js either devtool: "inline-source-map" or remove the two options od debug and devtool complete.
In my case I don't need them.
I had to add a filepath for the sourcemap file. Take a look at the output part of this webpack.config.js:
https://github.com/nwinger/reactreduxtodo/blob/master/webpack.config.js