npm build to two dist folder - javascript

I have a Gatsbyjs project and I'm trying to build into 2 different folders public and production.
The public folder will be used for development purposes.
I have tried npm build ./production. It is building into the public folder.

Despite not being a common purpose, you can achieve that changing you gatsby-node.js via Gatsby API (onPostBuild):
const path = require("path")
const fs = require("fs")
exports.onPreInit = () => {
if (process.argv[2] === "build") {
fs.rmdirSync(path.join(__dirname, "dist"), { recursive: true })
fs.renameSync(
path.join(__dirname, "public"),
path.join(__dirname, "public_dev")
)
}
}
exports.onPostBuild = () => {
fs.renameSync(path.join(__dirname, 'public'),
path.join(__dirname, 'dist'), { overwrite: true })
fs.renameSync(
path.join(__dirname, "public_dev"),
path.join(__dirname, "public")
)
}
In the example above, you will output in/dist when running gatsby build command.
Useful GitHub issues:
https://github.com/gatsbyjs/gatsby/issues/18975
https://github.com/gatsbyjs/gatsby/issues/14703

Related

Using environment variables in split webpack configuration

I'm reading the webpack docs on environment variables. In order to use the env variable they convert the module.exports into a function.
How do I perform this "conversion into a function" if my module.exports object is split across two files:
webpack.common.js:
const path = require("path");
const Dotenv = require("dotenv-webpack");
//Other stuff.
module.exports = {
entry: {
app: "./src/app.tsx",
},
module: {
rules: loaders,
},
resolve: {
extensions: [".tsx", ".ts", ".js", ".jsx"],
},
output: {
filename: "main.bundle.js",
path: path.resolve(path.resolve(), "../dist"),
},
plugins: [new Dotenv({ path: "../backend/.env.development" })], //Wish to be able to change the path depending on 'env'
};
webpack.dev.js:
const path = require("path");
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");
const fs = require("fs");
module.exports = merge(common, {
devtool: "inline-source-map",
mode: "development",
devServer: {
static: {
directory: path.join(path.resolve(), "../dist"),
},
port: 3000,
http2: true,
https: {
key: fs.readFileSync("../pathtokey.pem"),
cert: fs.readFileSync("../pathtocert.pem"),
},
},
});
If I simply convert both objects in both files into functions, it errors out.
The reason for my attempt is that I'm trying to gain access to a webpack environment variable env so that I may tell dotenv-webpack which .env file to refer to (either "development" or "production", in webpack.common.js). I'm also new to this so any tips are appreciated.

How to set basePath for a static exported NextJS app

I need to build and deploy a React / NextJS app to a Weblogic J2ee server with a specific context. I have some React experience, but taking my first steps with NextJS.
Currently the build/verification steps are;
Create a vanilla NextJS app
Add a next.config.js with a module.export to change the basepath
module.exports = {
basePath: '/test'
}
Execute npm run dev the application is available on 'http://localhost:3000/test'
Add an export script to the package.json "export": "next build && next export" to support static export
Add the export below to resolve issue 21079
//https://github.com/vercel/next.js/issues/21079
module.exports = {
images: {
loader: "imgix",
path: "",
}
}
Executed npm run export to create a static HTML export. Export is completed successfully to the out folder.
When inspecting the index.html in the out folder, all references to the static content still starts with /_next/static and not with /test/_next/static.
So this can be a misinterpretation of my side, please correct me if i am wrong here.
To be able to test the vanilla app on the J2EE applicationserver it has to be packed into a war file. To accomplish this i added the file warpack/warpack.ts to the project.
const fs = require('fs');
const archiver = require('archiver');
const rimraf = require('rimraf') ;
const distFolder = 'dist' ;
const warFile = distFolder + '/test.war';
const buildFolder = 'out';
const contextRoot = 'test';
// Destroy dist folder
rimraf(distFolder, (error) => {
if (!error) {
// Create dist folder
if (!fs.existsSync(distFolder)){
fs.mkdirSync(distFolder);
}
const output = fs.createWriteStream(warFile);
const archive = archiver('zip', {});
output.on('close', () => {
console.log('war (' + warFile + ') ' + archive.pointer() + ' total bytes');
});
// write archive to output file
archive.pipe(output);
// add build folder to archive
archive.directory(buildFolder,'');
// add weblogic.xml
const weblogicXML = '<?xml version="1.0" encoding="UTF-8"?><weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.2/weblogic-web-app.xsd"><weblogic-version>10.3.6</weblogic-version><context-root>' + contextRoot '</context-root><description>Test NextJS</description></weblogic-web-app>'
archive.append(weblogicXML,{ name: 'WEB-INF/weblogic.xml' });
const manifestMF = 'Manifest-Version: 1.0\nBuild-Tag: 0.0.1-SNAPSHOT\nWeblogic-Application-Version: 0.0.1-SNAPSHOT';
archive.append(manifestMF,{ name: 'META-INF/MANIFEST.MF' });
archive.finalize();
} else {
console.log('Failed to delete "' + distFolder + '" folder.') ;
process.exit(1);
};
});
Installed the required packages for webpack.ts
npm install fs --save-dev
npm install rimraf --save-dev
npm install archiver --save-dev
Added the script "warpack": "next build && next export && node warpack/warpack.ts" to build, export and pack the static app to an war.
After deployment of the war-file the page can be loaded on http://something/test but shows an empty page.
Network development tools indicate that the requests are made to the root of the application server, not to the configured basepath.
GET http://host:8001/static/css/main.09371e9d.chunk.css net::ERR_ABORTED 404 (Not Found)
GET http://host/static/js/2.0850eeb7.chunk.js net::ERR_ABORTED 404 (Not Found)
GET http://host/static/js/main.dc0c945b.chunk.js net::ERR_ABORTED 404 (Not Found)
​
Too much focus on basePath value instead on correct syntax of next.config.js.
Second module export in next.config.js overwrote first.
Wrong
module.exports = {
basePath: '/test'
}
//https://github.com/vercel/next.js/issues/21079
module.exports = {
images: {
loader: "imgix",
path: "",
}
}
Correct
module.exports = {
basePath: '/test',
assetPrefix: "/test/",
//https://github.com/vercel/next.js/issues/21079
images: {
loader: "imgix",
path: ""
}
}
You can use env check to invoke only for prod environment if you wish to like:
module.exports = {
basePath: "/test"
assetPrefix: process.env.NODE_ENV === "production" ? "/test/" : undefined,
}

problems with vue-cli for production

I am currently working on a vue-cli app,but I am having problems to run the app on production locally. After finishing everything on the dev environment I used the following command to build my production version of the app.
npm run build
the following is my config/prod.env.js file:
'use strict'
module.exports = {
NODE_ENV: '"production"'
}
config/index.js file:
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}
config/dev.env.js:
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})
build/build.js:
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // if you are using ts-loader, setting this to true will make typescript errors show up during build
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
it created a dist folder in which I initialised a package.json and installed express on it:
package.json:
{
"name": "project_gorilla_production",
"version": "0.0.0",
"description": "THe production version for project gorilla",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"ProjectGorilla",
"BkChatLDN",
"zezemills"
],
"author": "Christopher Salay",
"license": "ISC",
"dependencies": {
"express": "^4.16.4"
}
}
my server.js file:
const express = require('express');
const app = express();
const path = require('path');
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(process.env.PORT || 8000, function(){
console.log('Your node js server is running');
})
index.html file:
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>project_gorilla</title><script src=https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js></script><link href=/static/css/app.b2785d7282208bedd7a467d4d7584204.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.91dc1c7d90da0f3312fd.js></script><script type=text/javascript src=/static/js/app.75194bcb7c3977e313be.js></script></body></html>
I get the following error when I run node server.js:
Refused to apply style from 'http://localhost:8000/static/css/app.b2785d7282208bedd7a467d4d7584204.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
and a lot of my files such as the manifest, the vendor and the app js files gives of a 404 error.

dotenv not working with serverless/webpack

EDIT: If I log out dotenv.config() I get an error of : Error: ENOENT: no such file or directory, open '/Users/myPathToApplication/.webpack/test/.env'
I am bundling my serverless handler in order to use es6/es7 code. I have some env variables that I am trying to use as well. The problem is it seems that dotenv is not working when I bundle the handler.
For example one of the utils I am using is connecting mongoose to my application. In here I store the DB_URI as an env variable. import envdotjs from 'envdotjs';
import mongoose from 'mongoose';
mongoose.Promise = global.Promise;
require('dotenv').config();
let isConnected;
const connectToDatabase = () => {
if (isConnected) {
console.log('=> using existing database connection');
return Promise.resolve();
}
console.log('=> using new database connection');
return mongoose.connect(process.env.DB_URI).then(db => {
isConnected = db.connections[0].readyState;
});
};
module.exports = {
connectToDatabase
};
However the DB_URI is undefined and the code breaks.
Here is my webpack:
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: slsw.lib.entries,
target: 'node',
devtool: 'source-map',
externals: [nodeExternals()],
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
include: __dirname,
exclude: /node_modules/
}
]
}
};
I am running this in order to use es6/7 on serverless handler which is working just fine. But the env variables are breaking. I also tried using a module called envdotjs and got the same results that the env variables are undefined so I don't think this is a problem with dotenv.
I found a package dotenv-webpack also recommended by #apokryfos. Just require it in const Dotenv = require('dotenv-webpack') and include it in the webpack.config.js.
module.exports = {
...
plugins: [new Dotenv()]
}
Just include your .env in the root with your webpack.config.js and you can declare your process.env. anywhere you need to with no other configuration.

webpack.optimize.UglifyJSPlugin does not work while uglifyjs-webpack-plugin works

I have 2 files app.js & math.js
It contains the following code -
app.js
import { sum } from "./math";
console.log("💩");
console.log(sum(2, 3));
math.js
export const sum = (a, b) => a + b;
export const multiply = (m, n) => m * n;
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const config = {
entry: "./app.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
plugins: [
new UglifyJsPlugin()
// new webpack.optimize.UglifyJsPlugin() doesn't work
]
};
module.exports = config;
The complete code is available at https://github.com/deadcoder0904/webpack-treeshake
The problem is UglifyJsPlugin works but webpack.optimize.UglifyJsPlugin() doesn't work
My webpack version is v3.11.0
Posting answer to my own question. Thanks #str for helping out.
I was using different versions of Uglify JS, not sure if that was the problem.
So I tried installing webpack version 4 which is now in beta so I had to do install webpack#next. Also, webpack-cli is now its own package so I had to install it too. Earlier, it was bundled with webpack itself.
After installing both webpack#next & webpack-cli, I changed my webpack.config,js to look like -
webpack.config,js
const path = require("path");
const webpack = require("webpack");
const config = {
entry: "./app.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
}
};
module.exports = config;
And ran the following to generate bundle with TreeShaking
webpack --optimize-minimize --mode production
The complete code is available at https://github.com/deadcoder0904/webpack-treeshake
Checkout my other answer to TreeShake with Lodash which does all the treeshaking

Categories

Resources