How to deploy Vue.js application on IIS over Virtual Directory? - iis

I need to deploy a Vue.js application on IIS over a virtual directory, but when I deploy it I have to change my routes to include the virtual directory name.
My original routes is like that:
export const routes = [
{ path: '', component: Default, props: true },
{ path: '/Path', component: Path, props: true },
{ path: '/Path/:IdPath', component: PathForm, props: true }
];
But to work, I had to change my routes to include the virtual directory name, like that:
export const routes = [
{ path: '/VirtualDirectory', component: Default, props: true },
{ path: '/VirtualDirectory/Path', component: Path, props: true },
{ path: '/VirtualDirectory/Path/:IdPath', component: PathForm, props: true }
];
And this is a problem, because if I need to change my server or my virtual directory I'll have to re-deploy my Vue.js application to include the new virtual directory name.
Are there a way to make this dinamic?

You will need to configure the publicPath, by default this is set to "/", e.g. if you look in your generated index.html you will see:
<script type="text/javascript" src="/app.js"></script></body>
Notice the "/app.js" above.
You can configure this by adding a vue.config.js file to the root of your project and adding a publicPath setting:
module.exports = {
publicPath: '/my-virtual-directory'
}
See the official Vue documentation https://cli.vuejs.org/config/#publicpath for more information.

If you are using webpack-cli, one thing you can do is to give your directory (mostly vuejs root dir) an alias. inside your webpack.config.js So, in this following example:
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': path.resolve(__dirname, 'src')
},
The # will be an alias to your /src directory. If you change this to reflect your current vue root, then you can migrate your app without a problem.

Related

Can't find path when build project in vue3

When I build the project and run it, The first page can run properly and the redirect is working but when I change the path it show Can't get /admin(path name) it's seems like I can't direct by typing the URL.
It's work fine when I run serve.
Here is my router index.js
import Blog from "../views/Blog.vue";
import Admin from "../views/Admin.vue";
const routes = [
{ path: "/", redirect: "/blog" },
{ path: "/blog",name: "blog",component: Blog },
{ path: "/admin", name: "admin", component: Admin },
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL), routes,
});
export default router;

Bundling files in "src" folder into "public" folder using webpack

How to Bundle all the files inside “src” folder and replace the existing bundled files inside “Public” folder in any Node.js web app?
My project structure is similar to this: https://github.com/googlearchive/friendlypix-web
For javascript files, you should have at least one entry-point for your application in order to bundle it.
Example of webpack.config.json with one entrypoint src/index.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public'),
},
};
More information about bundling one or many entry-points : https://webpack.js.org/concepts/entry-points/
Furthermore, if you have imported static assets (images, css, saas, fonts...) in your javascript files, you need to add some configuration and eventually install webpack loaders to bundle them.
For example, for CSS assets :
Install webpack loaders via npm install --save-dev style-loader css-loader
Update webpack configuration
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
More information about asset management : https://webpack.js.org/guides/asset-management/
Finally, you may need to bundle static files or directories that are not imported in your javascript files and you want to copy them as they are.
In this case, you could use the copy-webpack-plugin :
Install plugin via npm install copy-webpack-plugin --save-dev
Update webpack configuration
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
...
plugins: [
new CopyPlugin({
patterns: [
{ from: "source", to: "dest" },
{ from: "other", to: "public" },
],
}),
],
...
}
More info about copy-webpack-plugin : https://webpack.js.org/plugins/copy-webpack-plugin/
I really recommend you to take a look at the official webpack documentation which covers topics including creating production bundles, code splitting, caching and other tips and hints.

How to handle ejs views using webpack

I'm trying to configure webpack with my website using node js, I'm using also ejs as a view. I have tried with many ways to handle the ejs in my webpack, but till now I didn't get success.
const path = require('path')
const nodeExternals = require('webpack-node-externals')
module.exports = (env, argv) => {
return ({
entry: {
server: './src/app.js',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: 'main.js'
},
mode: argv.mode,
target: 'node',
node: {
// Need this when working with express, otherwise the build fails
__dirname: true,
__filename: true,
},
externals: [nodeExternals()], // Need this to avoid error when working with Express
module: {
rules: [
{
// Transpiles ES6-8 into ES5
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.ejs$/,
loader: 'ejs-loader',
options: {
esModule: false
}
}
]
}
})
}
when I use HtmlWebPackPlugin I get some errors because of data inside <%- %> it's like he didn't know this data where comes from. like for example, <%- include('partials/head.ejs') %>.
is there a way to handle my views as ejs using webpack?
I know this has been asked a few months ago. But for those who come across this issue like I have, this is how I got this to work. Assuming your using webpack 4.
If you have not already install html-webpack-plugin
Most importantly to help solve the issue install raw-loader
add the following to your webpack config
new HtmlWebpackPlugin({
template: '!!raw-loader!./src/views/pages/<file-name-here>.ejs',
filename: 'index.ejs',
chunks: ['main', 'owl_carousel']
})
This is where the magic is. when including the template path make sure to include !!raw-loader! followed by the relative path.
raw-loader makes it so when html plugin creates the file it ignores the special syntax ejs uses. It is basically like "hey plugin ignore whatever I put here and just get me my file".
As #JRichardsz explained, You won't need Webpack explicitly to use EJS templates in your NodeJS project.
Also, It simply bundles up the EJS template (code) implicitly.
Try to bundle up your files with latest Webpack.js using below command to install:
npm install --save-dev webpack
Also, try this code with a little fix:
module.exports = (env, argv) => {
return ({
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: 'main.js'
}
...
// in case, all of this doesn't work. Then, explicitly whitelist EJS using regex
...
nodeExternals({
whitelist: [/\.(?|ejs)$)],
}),
...
})
}
If you want to use ejs for nodejs projects, you don't need webpack. Webpack is commonly used for client side rendering like angular, vue, react, etc
Check this: Which command should I use to minify and optimize nodejs express application? to view some ways to optimize your static js files used in ejs or another nodejs server rendering framework.
Basic structure for ejs projects is:
|____
|____server.js
|____views
| |____hello.ejs
|____package.json
hello.ejs a simple and plain template in which you can use any of ejs code like your
<%- include('partials/head.ejs') %>
As you can see, you don't need webpack to run ejs apps.
Check these samples:
minimal ejs sample
partials sample
You would need to make bundle of the EJS.
Try below commands:
module.exports = (env, argv) => {
return ({
output: {
path: './dist',
publicPath: '/',
filename: 'main.js'
}
})
}
copy-webpack-plugin worked perfectly
plugins: [
new webpack.ProgressPlugin(),
new CopyWebpackPlugin({
patterns: [
{from: "src/views", to: "views"}
]
})

Vue Website Returns "Cannot Get /path" On All Pages EXCEPT Index

I am using Vue on Node.js to host my website on an AWS EC2 instance. I dont have an index node.js file, just the vue-router file. I use AWS CloudFront to bind my certificate to my traffic. The problem is that everytime i access the site through the server's link, the site works perfectly, but whenever i access it through the cloud-front link, only the index of the website will show up. No /about or /contact; instead it returns Cannot GET /about.
My Router:
import Vue from 'vue';
import Router from 'vue-router';
import VueCookies from 'vue-cookies';
import Home from './views/Home.vue';
import NotFound from './views/NotFound.vue';
Vue.use(Router);
Vue.use(VueCookies);
VueCookies.config('7d');
VueCookies.set('theme', 'default');
VueCookies.set('unique', Date.now());
VueCookies.set('rwapi-uuid', `v3-${Date.now()}-x9k0`)
export default new Router({
mode: 'history',
routes: [
{ path: '/', name: 'INDEX', component: Home },
{ path: '/about/', name: 'ABOUT', component() { return import('./views/About.vue'); } },
{ path: '/portfolio', name: 'PORTFOLIO', component() { return import('./views/Port.vue'); } },
{ path: '/contact', name: 'CONTACT', component() { return import('./views/Contact.vue'); } },
{ path: '/login', name: 'LOGIN', component() { return import('./views/Login.vue'); } },
{ path: '/404', component: NotFound },
{ path: '*', redirect: '/404' },
],
});
I have already tried to add the historyApiFallback: true to my webpack config but it had no effect.
According to Vue Router's documentation, when using your router in history mode, your webserver requires additional configuration.
I don't exactly know how do EC2 instances work, but if you don't have a webserver proxying all your requests to index.html, Vue-router will not be able to handle the other requests.

Cannot get HotModuleReplace plugin with react-hot to be enabled in the browser, though file watching is working

I'm trying to use webpack's Hot Module Replacement plugin. I've managed to randomly get it working, but it still isn't doing quite what I would hope it to.
Basically, I get no messages in my console that it's even active, though it's building without issue and file watching is working, as I get the messages webpack: bundle is now VALID and webpack: bundle is now INVALID when I update.
webpack, webpack-dev-server, and react-hot are all installed locally.
But in the browser's console, the only thing I see is:
Download the React DevTools for a better development experience: https://fb.me/react-devtools
I'm using Laravel to update my index file based on an environment variable and it is working just fine.
Here is the index.php file:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="content"></div>
#if(env("APP_HOTRELOAD"))
<script src="http://localhost:8080/js/vendor.js"></script>
<script src="http://localhost:8080/js/app.js"></script>
#else
<script src="js/vendor.js"></script>
<script src="js/app.js"></script>
#endif
</body>
</html>
Here is the webpack config file (webpack.hot-reload.config.js):
var path = require("path");
var webpack = require("webpack");
var node_modules = path.resolve(__dirname, "node_modules");
var public_dir = path.resolve(__dirname, "public");
module.exports = {
debug: (process.env.NODE_ENV === "production"),
entry: {
vendor: [
"es5-shim",
"es5-shim/es5-sham",
"babel-core/polyfill",
"babel-core/external-helpers",
"react",
"react-router-component"
],
app: [
"webpack-dev-server/client?http://localhost:8080",
"webpack/hot/only-dev-server",
path.resolve(__dirname, "resources/assets/js/index.js")
]
},
contentBase: public_dir,
output: {
path: path.resolve(public_dir, "js"),
filename: "app.js",
publicPath: "/"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js"),
//This is necessary for React to know whether it's supposed to strip out
//addons and extra stuff when being minified. Essentially, it becomes dead
//code and webpack will take it out.
new webpack.DefinePlugin({
"process.env": {"NODE_ENV": JSON.stringify(process.env.NODE_ENV)}
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
module: {
loaders: [
{
test: /\.(sa|c)ss$/,
loader: "css!style!sass"
},
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loaders: [
"react-hot",
"strip-loader?strip[]=debug,strip[]=console.log,strip[]=console.error",
"babel-loader"
]
}
]
},
resolve: {
root: path.resolve(__dirname, "resources/assets/js"),
extensions: ["", ".js", ".json"]
}
};
In order to start the webpack-dev-server, I use a separate server.js file, executed by using node server.js:
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.hot-reload.config');
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
contentBase: config.contentBase,
hot: true,
historyApiFallback: true,
quiet: false,
noInfo: false,
stats: {
colors: true
}
}).listen(8080, 'localhost', function (err, result) {
if (err) {
console.log(err);
}
console.log('Listening at localhost:8080');
});
It seems to work randomly after waiting some time, but if I change a file or refresh the page manually, it seems to just break. I've tried using both Firefox and Chrome and it doesn't make a difference, so I'm thinking it's in the build.
What could be wrong?
I figured it out. There was a comment about it on the page that notes how to use webpack-dev-server, but I managed to read over it.
If you look in my config you'll see:
...
output: {
path: path.resolve(public_dir, "js"),
filename: "app.js",
**publicPath: "/"**
},
...
I misinterpreted the publicPath key and its path.
However, the example given in the docs shows:
module.exports = {
entry: {
app: ["./app/main.js"]
},
output: {
path: "./build",
publicPath: "/assets/",
filename: "bundle.js"
}
};
And states:
This modified bundle is served from memory at the relative path specified in publicPath (see API). It will not be written to your configured output directory. Where a bundle already exists at the same url path the bundle in memory will take precedence.
However, for this example, this bundle will be served from /, not /assets/ because further down, the content base is given as build/. There's nothing that notes that the directory where the scripts lie is possibly aliased to /assets/ at all, so that's why I placed the / path as the publicPath instead of the subdirectory my JS was actually being served from..
The docs note that:
To teach webpack to make requests (for chunk loading or HMR) to the webpack-dev-server you need to provide a full URL in the output.publicPath option.
So I changed:
publicPath: "/"
to:
publicPath: "http://localhost:8080/js/"
And now my files are being served up correctly. I added the /js/ because that's where I my JavaScript is served from on the actual server.

Resources