I want to be able to build server-bundle.js using vue-server-renderer/server-plugin. When I run my webpack config using the command: webpack --config ./webpack/webpack.server.js --mode production, I get the following tip:
[vue-server-renderer-webpack-plugin] It is recommended to externalize dependencies in the server build for better build performance.
That is, it cannot produce server-bundle.js in /disk; it only produced vue-ssr-server-bundle.json. Why is this?
My config is:
const { merge } = require('webpack-merge');
const base = require('./webpack.base.js');
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
module.exports = merge(base, {
entry: {
server: './src/entry/server.entry.js'
},
output: {
libraryTarget: 'commonjs2'
},
target: 'node',
plugins: [
new VueSSRServerPlugin()
]
});
import createApp from '../main.js';
export default function () {
const { app } = createApp();
return app;
}
From what I understand if you were to create a react app without a starter kit e.g create-react-app, one of things you have full control of is webpack.
This is comes in particularly handy when you need to solve the problem when your app hits a route before the app is fully loaded.
https://your-app.com/login
You'll get an error because your routes haven't been created.
So you do something like this:
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
var webpack = require('webpack');
var config = {
output: {
publicPath: '/',
}
devServer: {
historyApiFallback: true,
}
mode: 'development',
};
if (process.env.NODE_ENV === 'production') {
config.plugins.push(
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
},
}),
new UglifyJSPlugin()
);
}
module.exports = config;
Specifically:
devServer: {
historyApiFallback: true,
}
So I found this enter link description here based on this related question
Any ideas, if there is package or TUT to solve this problem?
I have suddenly started hitting Uncaught ReferenceError: webpackJsonp in Vue Js. I am fairly new to Js and have just started with Vue applications. I tried the various solutions that were mentioned in the Git and stackoverflow but they have not worked. Can someone help me out.
To give some context, the issue suddenly appeared without having made much of a change. The code is working when it was in the state earlier but making any change in the components even modifying the css has started causing the issue.
Based on what I read about the issue, it is supposed to be controlled by the webpack.prod.conf.js (Attached mine below). Incase any other info is needed please let me know.
"use strict";
const path = require("path");
const utils = require("./utils");
const webpack = require("webpack");
const config = require("../config");
const merge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.conf");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const OptimizeCSSPlugin = require("optimize-css-assets-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const env = require("../config/prod.env");
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath("js/[name].[chunkhash].js"),
chunkFilename: utils.assetsPath("js/[id].[chunkhash].js")
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
"process.env": env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath("css/[name].[contenthash].css"),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap ?
{ safe: true, map: { inline: false } } :
{ safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: "index.html",
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: "dependency"
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
async: false,
minChunks(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(path.join(__dirname, "../node_modules")) === 0
);
// return module.context && module.context.includes("node_modules");
}
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: "app",
async: "vendor-async",
children: true,
minChunks: 3
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: "manifest",
async: false,
minChunks: Infinity
}),
// copy custom static assets
new CopyWebpackPlugin([{
from: path.resolve(__dirname, "../static"),
to: config.build.assetsSubDirectory,
ignore: [".*"]
}])
]
});
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require("compression-webpack-plugin");
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: new RegExp(
"\\.(" + config.build.productionGzipExtensions.join("|") + ")$"
),
threshold: 10240,
minRatio: 0.8
})
);
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
module.exports = webpackConfig;
The entry points are missing in the configuration, i.e. you are not informing webpack from where the application should start.
Also this issue is happening because you have mentioned vendor
please refer this link
I'm trying to run a vue ssr app on cloudflare workers.
I generated a new project using wrangler generate test
I installed vue using npm install vue#next and npm install #vue/server-renderer
I edited the index.js file like this:
const { createSSRApp } = require('vue')
const { renderToString } = require('#vue/server-renderer')
const app = createSSRApp({
data: () => ({ msg: 'hello' }),
template: `<div>{{ msg }}</div>`
})
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const html = await renderToString(app)
return new Response(html, {status: 200})
}
I then used wrangler dev to test it, but when I access the page I get this error:
ReferenceError: __VUE_PROD_DEVTOOLS__ is not defined
at Module.<anonymous> (worker.js:8:104768)
at n (worker.js:1:110)
at Object.<anonymous> (worker.js:8:104943)
at n (worker.js:1:110)
at worker.js:1:902
at worker.js:1:912
Any help or guidance is appreciated
I faced similar issue and was able to fix it by defining a global constant (VUE_PROD_DEVTOOLS = false) during compile time.
Here is how my webpack prod config looks like:
const webpack = require('webpack');
const { merge } = require("webpack-merge");
const webpackCommon = require("./webpack.common");
const prodConfig = {
mode: 'production',
plugins: [
new webpack.DefinePlugin({
__VUE_PROD_DEVTOOLS__: JSON.stringify(false)
}),
]
};
module.exports = merge(webpackCommon, prodConfig);
I'm new to webpack so it's probably a stupid mistake on my part.
This is my project setup (root, atleast the relevant part):
+-- public
| |
| +-- index.html
|
+-- src
| |
| +-- App.vue
| +-- main.js
| +-- assets
|
+-- package.json
|
+-- webpack.config.js
Now I would like to use the webpack-dev(and hot)-middleware to serve my index.html and create a bundle in memory from my src folder. Now I can get the middleware set up (via the npm page) and I see the bundle gets created (through logging in console) but two things are not clear to me:
How to serve index.html
How to use the bundle thats created in memory?
Can somebody please explain how that middleware works exactly? This is my webpack config file (which is needed to plug into the middleware, it's just a copy of the webpack config file that gets created through the vue-cli):
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
// vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
devtool: '#eval-source-map'
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}
I know this is probably not the correct configuration, can someone maybe point out some things?
Thanks in advance for your help!
Edit (this setup works):
My server.js now:
var express = require('express');
var logger = require('morgan');
var bodyParser = require('body-parser');
var exphbs = require('express-handlebars');
var helmet = require('helmet');
var redis = require('redis');
var redisAdapter = require('socket.io-redis');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
// use the redis adapter to create sticky sessions, this is needed because of the different clusters
io.adapter(redisAdapter( require('./app/lib/config').credentials.redis.url ));
//setup security ===============================================================
require('./app/lib/security-setup')(app, helmet);
// configuration ===============================================================
app.use(logger('dev')); // log every request to the console
// set up our express application ==============================================
// Make the body object available on the request
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//set handlebars as default templating engine
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
// serve the static content ====================================================
if (app.settings.env === 'development') {
var webpackConfig = require('./webpack.config.js')
var compiler = require('webpack')(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
})
var hotMiddleware = require('webpack-hot-middleware')(compiler)
app.use(devMiddleware)
app.use(hotMiddleware)
} else {
app.use(express.static(__dirname + '/public'));
}
// set up global variables =====================================================
app.use(function(req, res, next) {
//set the io object on the response, so we can access it in our routes
res.io = io;
next();
});
// routes ======================================================================
require('./app/routes.js')(app); // load our routes and pass in our app
// export so bin/www can launch ================================================
module.exports = {app: app, server: server};
my ./bin/www:
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../server').app;
var cluster = require('cluster');
var debug = require('debug')('temp:server');
var http = require('http');
var numCPUs = process.env.WORKERS || require('os').cpus().length;
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
// If a worker dies, log it to the console and start another worker.
cluster.on('exit', function(worker, code, signal) {
console.log('Worker ' + worker.process.pid + ' died.');
cluster.fork();
});
// Log when a worker starts listening
cluster.on('listening', function(worker, address) {
console.log('Worker started with PID ' + worker.process.pid + '.');
});
} else {
/**
* Create HTTP server.
*/
var server = require('../server').server;
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
}
// The rest of the bin/www file.....
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
debug('Listening on ' + bind);
}
My working webpack.config.js:
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: [
'webpack/hot/dev-server',
'webpack-hot-middleware/client',
'./src/main.js'
],
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
// vue-loader options go here
}
},
{
test: /\.less$/,
loader: "style!css!less"
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
devtool: '#eval-source-map',
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.resolve(__dirname, 'public/index.html'),
inject: true
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}
How to serve index.html
To serve the index.html file you need to have a dev server running. It sounds like you are successfully doing this based on your logging of the creation of your bundle in memory. However I can't see a file for it in your set up? I've assumed another file below called: dev-server.js and it would be your entry point to serving your app, i.e. npm run dev:
package.json
"scripts": {
"dev": "node dev-server.js",
...
In webpack this dev server is generally going to be express and it's the config that you pass to your express server that will serve your index.html. As you are wanting hot-reloading you will pass express your webpack config through your middleware layers.
For hot reloading you'll need two main middlewares:
webpack-dev-middleware
webpack-hot-middleware
Then you will need to pass your config to webpack and pass your webpack compiler to the middleware, i.e.
dev-server.js
var app = require('express')()
var webpackConfig = require('./webpack.config.js')
var compiler = require('webpack')(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
})
var hotMiddleware = require('webpack-hot-middleware')(compiler)
app.use(devMiddleware)
app.use(hotMiddleware)
Now the key file becomes your webpack config, referenced above as: ./webpack.config.js
This leads to your next question: How to use the bundle thats created in memory?
The file you posted above looks to be about right and the key parts in regards to using the bundle are held within the output, you have:
webpack.config.js
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
You are creating the bundle at dist/build.js relative to the current working directory. This is essentially where you need to point any references to that file within your index.html, i.e. <script src="/dist/build.js"></script>
How you do this can be manual however we'd often add a further webpack plugin to automatically build this script tag within your output html (again in this case in memory):
webpack.config.js
plugins: [
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.resolve(__dirname, 'public/index.html'),
inject: true
}),
...
The HtmlWebpackPlugin is now essentially how you reference what the output file is called: filename and crucially where it is stored: template so if you wanted to move your index.html file this is where you tell webpack where to find it. The HtmlWebpackPlugin will now place the output 'index.html' at the publicPath referenced earlier, so to get to this file you would call /dist/index.html.
Finally you'll need some further plugins for hot reloading so your entire webpack plugins array will look like:
webpack.config.js
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'bar/index.html',
inject: true
})
]
Now we return to the dev-server.js file - or whatever yours is called that you are configuring express within - and fire up the configured express server:
dev-server.js
module.exports = app.listen(8080, function (err) {
if (err) {
console.log(err)
return
}
})
so with the above config you'd open the following uri: localhost:8080/dist/index.html