Let's say I have 2 files which are .env.development and .env.production.
In my package.json, since the mode is development, it should access .env.development for the variables.
"scripts": {
"start": "webpack-dev-server --config ./webpack.config.js"
webpack.config.js
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const Dotenv = require("dotenv-webpack");
module.exports = {
mode: "development",
entry: path.resolve(__dirname, "./src/index.jsx"),
devtool: "source-map",
output: {
path: path.join(__dirname, "/dist"),
filename: "bundle.js",
},
devServer: {
port: 3000,
static: true,
historyApiFallback: true,
open: true,
},
resolve: {...},
module: {...},
plugins: [
new Dotenv(),
new HtmlWebpackPlugin({
template: "public/index.html",
filename: "index.html",
favicon: "public/favicon.ico",
}),
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
}),
new webpack.ProvidePlugin({
process: "process/browser",
}),
],
};
So that in the frontend, when I use process.env, it will access the variable in .env.development.
Is there any way to do it?
You can set the system environment variable NODE_ENV at the beginning of the npm script. Use this environment variable to control the built environment.
E.g.
package.json:
"scripts": {
"build:dev": "webpack",
"build": "NODE_ENV=production webpack",
"dev": "webpack serve"
}
webpack.config.js:
const path = require("path");
const Dotenv = require("dotenv-webpack");
const mode =
process.env.NODE_ENV === "production" ? "production" : "development";
console.log("mode: ", mode);
module.exports = {
mode,
entry: path.resolve(__dirname, "./src/index.jsx"),
devtool: "source-map",
output: {
path: path.join(__dirname, "./dist"),
clean: true,
},
devServer: {
port: 3000,
static: true,
historyApiFallback: true,
open: true,
},
plugins: [
new Dotenv({
path: path.resolve(__dirname, `./.env.${mode}`),
}),
],
};
.env.development:
PWD=123456
.env.production:
PWD=a)d4125z
For development build npm run build:dev, the output of ./dist/main.js:
/******/ (() => { // webpackBootstrap
var __webpack_exports__ = {};
/*!***********************!*\
!*** ./src/index.jsx ***!
\***********************/
console.log("PWD: ", "123456");
/******/ })()
;
//# sourceMappingURL=main.js.map
For production build npm run build, the output:
console.log("PWD: ","a)d4125z");
//# sourceMappingURL=main.js.map
Related
I am requesting help setting up the compilation and dev environment for a typescript library. The library should work when consumed by a web app framework and when consumed by a script tag. I am currently using Webpack as a dev server so I can debug and TSC to build (cjs + esm). The issue that prompted this post was having to constantly switch my API strings between http://localhost:8080 to https://production.com. What tools or changes do I need in order to build dev and prod variables into my compilation?
Here is what I'm doing so far:
package.json fragment
"main": "./lib/cjs/index.js",
"module": "./lib/esm/index.js",
"files": [
"lib/**/*",
"README.md"
],
"scripts": {
"build:esm": "tsc -p tsconfig.json --outDir lib/esm --module ES2020 --sourceMap false",
"build:cjs": "tsc -p tsconfig.json --outdir lib/cjs --module commonjs --sourceMap false",
"clean:build": "rimraf lib",
"clean:serve": "rimraf dist",
"build": "rimraf lib && npm run build:esm && npm run build:cjs",
"serve": "rimraf dist && webpack-dev-server"
}
webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const SRC = path.resolve(__dirname, 'src')
const ENTRTY = path.resolve(__dirname, 'src', 'debug.ts')
const DIST = path.resolve(__dirname, 'dist')
module.exports = {
mode: 'development',
context: SRC,
entry: ENTRTY,
output: {
path: DIST,
filename: 'index.js',
},
devtool: 'source-map',
devServer: {
contentBase: DIST,
writeToDisk: true,
host: '0.0.0.0',
port: 8080,
https: true,
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin()
],
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
include: [SRC]
}
]
}
}
My toolchain does not currently allow me to do do this:
import Axios from 'axios'
import SocketIO from 'socket.io-client'
export const axios = Axios.create({
baseURL: process.env.SERVER_HTTP_URL, //<-- can't do env-vars with tsc build
withCredentials: true
})
typescript cant not do that, but gulp can do it
const replace = require('gulp-replace');
const { src, dest } = require('gulp');
exports.default = function() {
return src(['*.js'], {base: './'})
.pipe(replace('__XXXX__', 'some variables'))
.pipe(dest('./'));
}
This is the error:
'node"' is not recognized as an internal or external command,
operable program or batch file.
[Finished in 0.139s]
Also, this is coming from atom text editor, if that's necessary information.
Here's my code:
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const isProduction = process.env.npm_lifecycle_event === 'build'
module.exports = {
entry: './src',
// resolve: {
// alias: {
// 'src': path.join(__dirname, '/src'),
// 'libs': path.join(__dirname, '/src/libs'),
// }
// },
devtool: !isProduction && 'source-map',
output: {
path: path.join(__dirname, '/dist'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader'
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html',
// minify: isProduction && {
// collapseWhitespace: true
// },
minify: isProduction,
inlineSource: isProduction && '\.(js|css)$'
}),
new HtmlWebpackInlineSourcePlugin(),
new OptimizeCssAssetsPlugin({}),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
new CopyWebpackPlugin([
{ from: './src/assets/**/*', to: path.join(__dirname, '/dist'), flatten: false, force: true },
]),
],
devServer: {
stats: 'minimal',
overlay: true,
contentBase: path.resolve('src/assets'),
// contentBase: path.join(__dirname, '/src/assets'),
}
}
Am I just missing a package for this, or is there an error in my quote, or what?
Mmmmm... how are you running the code?
Most probable answer, based on your provided info --> you have any node installation in your system and/or your node installation is not accesible or included into your path.
Check https://nodejs.org/en/download/
Taken from webpack docs:
Since webpack v5.0.0-beta.1 the minimum Node.js version to run webpack
is 10.13.0 (LTS)
You need to install node.js
What I'm trying to achieve is to create a separate webpack assets file for copying static assets from the src folder to the web folder.
node version: 8.15.0
yarn version: 1.13.0
webpack: 4.19.1
copy-webpack-plugin: 6.0.0
To start, I already have a webpack.common.js file which deals with all the js files, and I have created the assets file, which can be seen below.
When I run
webpack --config=webpack/webpack.assets.js --mode development --progress --color
or
webpack --config=webpack/webpack.config.js --config=webpack/webpack.assets.js --mode development --progress --color --env development
I get this error ERROR in Path must be a string. Received undefined and I can't figure it out where it comes from.
By the way I just started dealing with webpack recently.
webpack.common.js
const webpack = require('webpack');
const path = require('path');
const PATHS = {
src: path.join(process.cwd(), 'src', 'js'),
dist: path.join(process.cwd(), 'web', 'js')
};
module.exports = {
entry: {
homepage: path.resolve(PATHS.src, 'pages/homepage.js'),
otherfile: path.resolve(PATHS.src, 'pages/othefile.js'),
}
output: {
path: PATHS.dist,
filename: '[name].js',
chunkFilename: '[name].js',
publicPath: '/js/'
},
...
}
webpack.assets.js
const webpack = require('webpack');
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const PATHS = {
src: path.join(process.cwd(), 'src', 'svg'),
dist: path.join(process.cwd(), 'web', 'svg')
};
module.exports = (env) => {
const svgFormat = env === 'production' ? '[name].[hash].[ext]' : '[name].[ext]';
return merge(commmonConfig, {
entry: [
path.resolve(PATHS.src, 'logo1.svg'),
path.resolve(PATHS.src, 'logo2.svg')
],
output: {
path: PATHS.dist
},
module: {
rules: [
{
test: /\.(svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: svgFormat,
},
},
],
},
]
},
plugins: [
new CopyPlugin([
{
from: PATHS.src,
to: PATHS.dist,
force: true,
toType: 'dir'
},
{
copyUnmodified: true,
debug: 'debug'
}
])
]
});
};
What I would like is to be able to run the assets commands with no errors, as the actual files get copied correctly.
Any ideas are very much appreciated!
You have passed your options object as a second pattern.
Move it outside of the patterns array and pass it as the second parameter instead:
plugins: [
new CopyPlugin(
[
{
from: PATHS.src,
to: PATHS.dist,
force: true,
toType: 'dir'
}
],
{
copyUnmodified: true,
debug: 'debug'
}
)
]
You get the error as your options object is being treated as a pattern but does not have a from property.
update:
Seem I have solved my problem creating an "hot directory" in my webpack config like that :
My webpack.config.js :
output: {
path: path.join(__dirname, "public"),
filename: "bundle.js",
publicPath: "/public/",
hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json'
}
My new tree folders :
├── hot
├── package.json
├── src
└── webpack.config.js
But I still wonder how purely create these chunks in memory ?
Any hint would be great,
Thanks
I'm trying currently to work with express hot middleware. I have set my webpack.config, server.js and package.json to work with. It works fine now but generates a lot of bundles on my root directory instead of on memory, hence saturate my root's directory. I can't figure out what is wrong.
The bundle have name like the following :
main.0d50bece383b2f7c93db.hot-update.js
They are created when there is a change on my server or more generally, configuration files it seems.
Here my webpack.js :
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const autoprefixer = require("autoprefixer");
const nodeExternals = require('webpack-node-externals');
const path=require("path");
module.exports = {
mode:"development",
entry: [
"webpack-hot-middleware/client",
"./src/client/index.js"],
output: {
path: path.join(__dirname, "public"),
filename: "bundle.js",
publicPath: "/"
},
devtool: "cheap-module-source-map",
module: {
rules: [
{
test: [/\.svg$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: "file-loader",
options: {
name: "public/media/[name].[ext]",
publicPath: url => url.replace(/public/, "")
}
},
{
test: /js$/,
exclude: /(node_modules)/,
loaders: "babel-loader",
}
]
},
plugins: [
new ExtractTextPlugin({
filename: "css/[name].css"
}),
new (webpack.optimize.OccurenceOrderPlugin || webpack.optimize.OccurrenceOrderPlugin)(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.DefinePlugin({
'process.env.BROWSER': true,
}),
],
};
here my server.js :
app.use(
require("webpack-dev-middleware")(compiler, {
noInfo: true,
publicPath: webpackConfig.output.publicPath
})
);
app.use(require("webpack-hot-middleware")(compiler));
// main route
app.get("/", (req, res) =>{
res.sendFile(path.resolve(__dirname, "./public/index.html"))
compiler.outputFileSystem.readFile(filename, (err, result) => {
if (err) {
return next(err);
}
res.set('content-type', 'text/html');
res.send(result);
res.end();
});
});
my package.json :
"scripts": {
"starter": "nodemon ./starter.js",
"start-dev": "concurrently --kill-others 'npm run webpack' 'npm run devserver'",
"devserver": "NODE_ENV=development nodemon ./server.js",
"webpack": "NODE_ENV=development webpack --w --hot --inline",
"start": "NODE_ENV=production webpack & NODE_ENV=production node ./server.js "
}
Any hint would be great,
Thanks
I'm using react with webpack. My app worked well before using webpack-dev-server. Only the home page works now, the others return "404 not found". Maybe there's a problem in webpack.config.js ?
var webpack = require("webpack");
var path = require("path");
var BUILD_DIR = path.resolve(__dirname, "public");
var APP_DIR = path.resolve(__dirname, "app");
var config = {
entry: [
"webpack/hot/only-dev-server",
APP_DIR + "/main.js",
"webpack-dev-server/client?localhost:8080"
],
output: {
path: BUILD_DIR + "/dist",
filename: "bundle.js",
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [...],
},
devServer: {
noInfo: true,
hot: true,
inline: true
},
}
module.exports = config;
And my script in package.json:
"start": "webpack --watch & webpack-dev-server --content-base public"
Webpack generates well bundle file. So i think the webpack-dev-server is the one who causes this problem.
Thank you !
I've found the answer. For someone who has the same problem, we need to add "historyApiFallback: true" to devServerConfig:
devServer: {
noInfo: true,
hot: true,
inline: true,
historyApiFallback: true
},
can you change your npm script
"start": "webpack --watch & webpack-dev-server --content-base public"
to
"start": "webpack --watch & webpack-dev-server --content-base public/"
and see what happens? Otherwise I will comeback and assist you.