error using dotenv-webpack with react project - javascript

Hi I am trying to use dotenv-webpack with my webpack config file and I can't seem to figure what to do with the following error...
.definitions is not a valid Plugin property
- Maybe you meant to use
"plugin": [
["#babel/plugin-transform-runtime", {
"definitions": {
"process.env.REACT_APP_WEATHERAPI": "\"XXXXXXX\""
}
}]
]
I am following the docs for using dotenv-webpack.
Here is my webpack.config fileconst currentTask = process.env.npm_lifecycle_event;
const path = require("path");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { postcss } = require("postcss-mixins");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const fse = require("fs-extra");
const webpack = require("webpack");
const dotenv = require("dotenv-webpack");
const postCSSPlugins = [
require("postcss-import"),
require("postcss-mixins"),
require("postcss-simple-vars"),
require("postcss-nested"),
require("postcss-hexrgba"),
require("autoprefixer")
];
class RunAfterCompile {
apply(compiler) {
compiler.hooks.done.tap("Copy images", function () {
fse.copySync("./app/assets/images", "./docs/assets/images");
});
}
}
let cssConfig = {
test: /\.css$/i,
use: [
"css-loader?url=false",
{ loader: "postcss-loader", options: { plugins: postCSSPlugins } }
]
};
let pages = fse
.readdirSync("./app")
.filter(function (file) {
return file.endsWith(".html");
})
.map(function (page) {
return new HtmlWebpackPlugin({
filename: page,
template: `./app/${page}`
});
});
let config = {
entry: "./app/assets/scripts/App.js",
plugins: pages,
module: {
rules: [
cssConfig,
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-react", "#babel/preset-env"],
plugins: ["#babel/plugin-transform-runtime", new dotenv()] <---- ERROR HERE!
}
}
}
]
}
};
if (currentTask == "dev") {
cssConfig.use.unshift("style-loader");
config.output = {
filename: "bundled.js",
path: path.resolve(__dirname, "app")
};
config.devServer = {
before: function (app, server) {
server._watch("./app/**/*.html");
},
contentBase: path.join(__dirname, "app"),
hot: true,
port: 3000,
host: "0.0.0.0",
historyApiFallback: { index: "/" }
};
config.mode = "development";
}
if (currentTask == "build") {
cssConfig.use.unshift(MiniCssExtractPlugin.loader);
postCSSPlugins.push(require("cssnano"));
config.output = {
filename: "[name].[chunkhash].js",
chunkFilename: "[name].[chunkhash].js",
path: path.resolve(__dirname, "docs")
};
config.mode = "production";
config.optimization = {
splitChunks: { chunks: "all" }
};
config.plugins.push(
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({ filename: "styles.[chunkhash].css" }),
new RunAfterCompile()
);
}
module.exports = config;

EDIT: Your new dotenv() is placed inside the wrong plugins array. Docs.
It should be in the global plugins not in babel-loader. Since you already have generated an array of HtmlWebpackPlugin, you would have to add it to the existing array
Your plugins array should be:
let config = {
...
plugins: [
...pages,
new dotenv()
]
...
};

Related

Can't resolve 'path' in 'path' using description file: samplepath/package.json - Field 'browser' doesn't contain a valid alias configuration

I'm trying to run npm run build on files I've merged for a website. Unfortunately I always get this error. I think it has something to do with the paths but I'm not that good in JS/React to see where the error is.
Important part of the Index.html:
<body>
<div id="root"></div>
<script src="../src/index.js" type="text/jsx"></script>
</body>
Index.jsx
import ReactDOM from "react-dom";
import React from "react";
import App from "./components/App.jsx";
const init = async () => {};
ReactDOM.render(<App />, document.getElementById("root"));
init();
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
function initCanisterEnv() {
let localCanisters, prodCanisters;
try {
localCanisters = require(path.resolve(
".dfx",
"local",
"canister_ids.json"
));
} catch (error) {
console.log("No local canister_ids.json found. Continuing production");
}
try {
prodCanisters = require(path.resolve("canister_ids.json"));
} catch (error) {
console.log("No production canister_ids.json found. Continuing with local");
}
const network =
process.env.DFX_NETWORK ||
(process.env.NODE_ENV === "production" ? "ic" : "local");
const canisterConfig = network === "local" ? localCanisters : prodCanisters;
return Object.entries(canisterConfig).reduce((prev, current) => {
const [canisterName, canisterDetails] = current;
prev[canisterName.toUpperCase() + "_CANISTER_ID"] =
canisterDetails[network];
return prev;
}, {});
}
const canisterEnvVariables = initCanisterEnv();
const isDevelopment = process.env.NODE_ENV !== "production";
const frontendDirectory = "websitetwo_frontend";
const frontend_entry = path.join("src", frontendDirectory, "src", "index.html");
module.exports = {
target: "web",
mode: isDevelopment ? "development" : "production",
entry: {
index: path.join(__dirname, frontend_entry).replace(/\.html$/, ".js"),
},
devtool: isDevelopment ? "source-map" : false,
optimization: {
minimize: !isDevelopment,
minimizer: [new TerserPlugin()],
},
resolve: {
extensions: [".js", ".ts", ".jsx", ".tsx"],
fallback: {
assert: require.resolve("assert/"),
buffer: require.resolve("buffer/"),
events: require.resolve("events/"),
stream: require.resolve("stream-browserify/"),
util: require.resolve("util/"),
},
},
output: {
filename: "index.js",
path: path.join(__dirname, "dist", frontendDirectory),
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, frontend_entry),
cache: false,
}),
new webpack.EnvironmentPlugin({
NODE_ENV: "development",
...canisterEnvVariables,
}),
new webpack.ProvidePlugin({
Buffer: [require.resolve("buffer/"), "Buffer"],
process: require.resolve("process/browser"),
}),
],
// proxy /api to port 8000 during development
devServer: {
proxy: {
"/api": {
target: "http://127.0.0.1:8000",
changeOrigin: true,
pathRewrite: {
"^/api": "/api",
},
},
},
static: path.resolve(__dirname, "src", frontendDirectory, "assets"),
hot: true,
watchFiles: [path.resolve(__dirname, "src", frontendDirectory)],
liveReload: true,
},
};
Error
I have already searched for the error but it didnt solved it. What is wrong? Thank you for the help!

Problem with import / export ts modules in webpack

So I tried to make a webpack config for a website which is using typescript. Everything works but when I want to import some ts file which is not an entry I am getting an error:
Module not found: Error: Can't resolve '../module' in '/Users/user/Projects/Node/project/src/script'
How can I fix this? I guess webpack don't know about a file I try to import but what I should do? I am learning webpack and I couldn't find anything on the web.
folder structure:
/src
/util
-module.ts
/script
-index.ts
...
reason (index.ts):
import { sth } from "../util/module"; // <-----------
console.log(sth);
module:
export const sth = "Hello World!";
webpack config:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const path = require("path");
const fs = require("fs");
const generateEntry = () => {
const entry = {};
const entryDir = path.resolve(__dirname, "src/script");
fs.readdirSync(entryDir).forEach((file) => {
const filename = file.split(".")[0];
entry[filename] = path.resolve(__dirname, "src/script", file);
});
return entry;
};
const generateTemplates = () => {
const templates = [];
const templatesDir = path.resolve(__dirname, "src/templates");
fs.readdirSync(templatesDir).forEach((file) => {
const filename = file.split(".")[0];
templates.push(
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src/templates", file),
chunks: [filename]
})
);
});
return templates;
};
module.exports = {
entry: generateEntry(),
output: {
publicPath: "",
path: path.resolve(__dirname, "./dist"),
filename: "script/[name].[contenthash].js"
},
module: {
rules: [
{
test: /\.ts$/i,
loader: "ts-loader",
exclude: /node_modules/
},
{
test: /\.scss$/i,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
exclude: /node_modules/
},
{
test: /\.html$/i,
loader: "html-loader"
},
{
test: /\.(png|jpe?g|gif)$/i,
loader: "file-loader",
options: {
outputPath: "static",
name: "[name].[contenthash].[ext]"
}
}
]
},
devServer: {
contentBase: path.resolve(__dirname, "dist"),
compress: false,
port: 8654
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: "style/[name].[contenthash].css"
})
].concat(generateTemplates())
};
So adding
resolve: {
extensions: ['.ts']
}
inside webpack config fixed this for me :))))))

Why webpack 5 is ignoring NODE_ENV in one file, but reads in another

Facing weird problem, where Webpack 5 is reading parent file and ignoring
const isDev = process.env.NODE_ENV !== 'production';
But the same line is read in another file and result is correct.
Package JSON
"build:prod": "cross-env NODE_ENV=production webpack --config internals/webpack/webpack.prod.babel.js --color -p --progress --hide-modules --display-optimization-bailout",
Webpack Config
module.exports = (env, argv) => {
return {
entry: path.join(process.cwd(), 'index.js'),
target: 'node',
mode: 'production',
module: {
rules: [
{
test: /\.jsx?$/, // Transform all .js and .jsx files required somewhere with Babel
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
output: {
filename: 'server.bundle.js',
path: path.resolve(process.cwd(), 'build'),
},
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
nodeEnv: 'production',
},
plugins: [
new Dotenv({
path: path.join(process.cwd(), 'config', '.env.production'), // load this now instead of the ones in '.env'
}),
new webpack.EnvironmentPlugin({
NODE_ENV: JSON.stringify('production'),
}),
],
};
};
Index
const express = require('express');
const path = require('path');
const server = express();
require('./middlewares/frontendMiddleware')(server);
frontendMiddleware
module.exports = (app, options) => {
const isDev = process.env.NODE_ENV !== 'production';
if (isDev) { // <-- Thinks NODE_ENV isDev
const addDevMiddlewares = require('./addDevMiddlewares');
addDevMiddlewares(app, webpackConfig);
} else {
const addProdMiddlewares = require('./addProdMiddlewares');
addProdMiddlewares(app, options);
}
return app;
};
addDevMiddlewares
const isDev = process.env.NODE_ENV !== 'production';
if (isDev) {
... // <-- Nicely ignores, or maybe not, but this peace of code is not present in the final build.
} else{
... // <-- Goes here. All good!
}

Uncaught TypeError: fs.exists is not a function

I am having trouble with the fs module error in Node JS Application. I am using Webpack also,
My .js file:
const fs = require('fs');
const path = require('path');
const filePath = path.join(__dirname, '../../app/logs/logs.txt');
module.exports.displayInfo = (info, containerID = 'info-dock') => {
fs.exists(filePath, (exists) => {
if (exists) {
console.log('Present');
}
});
let message;
if (info.message) {
message = info.message;
} else {
message = 'No message supplied.';
}
};
My webpack config file :
const path = require('path');
module.exports = {
entry: './clientSide/index.js',
cache: true,
output: {
path: path.resolve(__dirname, './public/js/'),
filename: 'bundle.js',
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['env'],
},
},
],
},
devtool: 'source-map',
target: 'web',
node: {
fs: "empty"
}
};
When I am trying to run and call displayInfo method in my application, on the browser's console, I get an error: ncaught TypeError: fs.exists is not a function.
Does anybody know how to correct this?

Vuejs 2 Server side rendering - not working

I've been working on making my vuejs app function well with SSR but all of my tries failed. I really need help in this.
Please note that I'm using normal js files not .vue files with es6 and require the html templates using webpack require function.
The app works fine in development mode, however, when I start execute it using 'vue-server-renderer' and go to any route, this error will be thrown:
Error: render function or template not defined in component: anonymous
at normalizeRender (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6015:13)
at renderComponent (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6081:3)
at renderNode (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6065:7)
at render (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6257:5)
at RenderStream.render (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:6312:9)
at RenderStream.tryRender (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:96:12)
at RenderStream._read (/Users/salaahassi/dev/vue/magicum/node_modules/vue-server-renderer/build.js:125:12)
at RenderStream.Readable.read (_stream_readable.js:348:10)
at resume_ (_stream_readable.js:737:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
Also, when I disable javascript on my browser, even home page will disappear (that's of course because it's not working from the SSR).
Here is my webpack:
var path = require('path')
var webpack = require('webpack')
var HTMLPlugin = require('html-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var extractCSS = new ExtractTextPlugin('styles.css');
var options = {
// entry: './entry.client.js',
entry: {
app: './entry.client.js',
vendor: [
'vue',
'vue-router',
'vuex',
'vuex-router-sync',
'moment',
'axios'
]
},
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/',
filename: '[name].[hash].js',
},
module: {
noParse: /es6-promise\.js$/, // avoid webpack shimming process
rules: [
{
test: /\.html$/,
loader: 'raw-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.(png|jpg|gif|svg|woff|woff2|eot|ttf)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
},
{
test: /\.scss$/,
loader: extractCSS.extract('css-loader!sass-loader')
}
]
},
plugins: [
extractCSS,
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en|zh-tw)$/),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(process.env.NODE_ENV) || 'development',
'VUE_ENV': JSON.stringify(process.env.VUE_ENV) || 'client',
}
})
],
resolve: {
alias: {
'vue$': 'vue/dist/vue'
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
devtool: '#eval-source-map'
}
console.log("xxxxx ---node env---- xxxx", process.env.NODE_ENV);
console.log("xxxxx ---vue env---- xxxx", process.env.VUE_ENV);
if (process.env.NODE_ENV != 'development') {
options.entry = './entry.server.js';
options.target = 'node';
options.output.filename = 'bundle-server.js';
options.output.libraryTarget = 'commonjs2';
options.externals = Object.keys(require('./package.json').dependencies);
}
if (process.env.NODE_ENV == 'development') {
options.plugins = (options.plugins || []).concat([
new HTMLPlugin({
template: './index.html'
}),
// extract vendor chunks for better caching
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
})
]);
}
if (process.env.VUE_ENV == 'server') {
options.devtool = '#source-map'
options.plugins = (options.plugins || []).concat([
new webpack.optimize.UglifyJsPlugin({
//sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
}),
new CopyWebpackPlugin([
{from: './assets', to: 'assets'},
{from: './index.html'}
])
])
}
module.exports = options;
And here is my server entry file:
import { app, router, store } from './src/app'
export default context => {
// set router's location
router.push(context.url)
// call prefetch hooks on components matched by the route
const s = Date.now()
return Promise.all(router.getMatchedComponents().map(component => {
if (component.prefetch) {
return component.prefetch(store)
}
})).then(() => {
console.log(`data pre-fetch: ${Date.now() - s}ms`)
// set initial store on context
// the request handler will inline the state in the HTML response.
context.initialState = store.state
return app
})
}
Here is my server.js:
'use strict'
const fs = require('fs')
const path = require('path')
const resolve = file => path.resolve(__dirname, file)
const express = require('express')
// const favicon = require('serve-favicon')
const serialize = require('serialize-javascript')
const createBundleRenderer = require('vue-server-renderer').createBundleRenderer
const app = express()
// parse index.html template
const template = fs.readFileSync(resolve('./dist/index.html'), 'utf-8')
// create server renderer from real fs
const bundlePath = resolve('./dist/bundle-server.js')
let renderer = createRenderer(fs.readFileSync(bundlePath, 'utf-8'))
console.log(renderer);
function createRenderer (bundle) {
return createBundleRenderer(bundle, {
cache: require('lru-cache')({
max: 1000,
maxAge: 1000 * 60 * 15
})
})
}
var options = {
maxAge: '60d',
setHeaders: function(res, path, stat) {
// Webfonts need to have CORS * set in order to work.
if (path.match(/ttf|woff|woff2|eot|svg/ig)) {
res.set('Access-Control-Allow-Origin', '*');
}
}
};
var dist_path = '/dist/';
app.use(express.static(path.join(__dirname, dist_path), options));
console.log("............");
app.get('*', (req, res) => {
console.log(".....ROUTE.......", req.url);
console.log('renderer', renderer);
if (!renderer) {
return res.end('waiting for compilation... refresh in a moment.')
}
var s = Date.now()
const context = { url: req.url }
const renderStream = renderer.renderToStream(context)
let firstChunk = true
// console.log(html.head);
// res.write(html.head)
renderStream.on('data', chunk => {
if (firstChunk) {
// embed initial store state
if (context.initialState) {
res.write(
`<script>window.__INITIAL_STATE__=${
serialize(context.initialState, { isJSON: true })
}</script>`
)
}
firstChunk = false
}
res.write(chunk)
})
renderStream.on('end', () => {
res.end(template)
console.log(`whole request: ${Date.now() - s}ms`)
})
renderStream.on('error', err => {
throw err
})
})
const port = process.env.PORT || 3000
app.listen(port, () => {
console.log(`server started at http://localhost:${port}`)
})
Does your index.html template has the placeholder <!--vue-ssr-outlet-->?

Categories

Resources