include client side js in express.js - express

I've build a new app with an express-generator so i've got public dir with javascripts i guess for a client side. But i can't get access to this files.
My app.js has for an absolute path
app.use(express.static(path.join(__dirname, 'public')));
But when i put on my index.html page on the bottom of the body like this
<script type="text/javascript" src="/javascripts/main.js">
i've got an error inside a console with a 404 regarding to this script.

you need to install stylus and nib npm modules
var express = require('express')
, stylus = require('stylus')
, nib = require('nib')
function compile(str, path) {
return stylus(str)
.set('filename', path)
.use(nib())
}
app.use(stylus.middleware(
{ src: __dirname + '/public'
, compile: compile
}
))
app.use(express.static(__dirname + '/public'))

I am developing something similar. I have my javascript files inside js folder in public folder. This is my link to javascript and I am not getting any error:
<script src="js/options.js"></script>
I think you needed to remove a common slash in "src" tag or properly close the "script"

Related

How to download a PDF in Vue

So, here I've got a locally stored file named "its_me.pdf" in the assets folder.
I'm trying to reference a download to the PDF using an HTML tag
<a href="../assets/its_me.pdf" download>PDF</a>
It is a real PDF file, if I go double click on the file manually I can see it display and it's real. However, when I go to my application on: http://localhost:4200/its_me (name of route in which it lives), and click on the link, I get a "Failed - No File" error.
Based on #AkashBhave answer I was able to get to work this way.
In my script tag:
data () {
return {
publicPath: process.env.BASE_URL
}
}
then in my template.
<a:href="`${publicPath}whatever.pdf`" download="download">PDF</a>
Alternatively with webpack, in your vue.config.js you add this;
chainWebpack: config => {
config.module
.rule("pdf")
.test(/\.pdf$/)
.use("file-loader")
.loader("file-loader");
}
then in the script tag;
data () {
return {
pdfLink: require("#/assets/whatever.pdf"),
}
}
Finally, in the template;
<a :href="pdfLink" download="download">PDF</a>
Relative imports should work by default with Vue. Try putting your PDF file into the /public folder of your application.
You can then reference the file using string interpolation, like so:
<link rel="icon" href="<%= BASE_URL %>its_me.pdf">
More information is available at
https://cli.vuejs.org/guide/html-and-static-assets.html#interpolation
If that doesn't work, something might be wrong with your Webpack or build configuration.

vuejs history mode with github/gitlab pages

Has anyone managed to figure out how to make Vue.js work with history mode with GitHub or GitLab Pages?
It works with hash mode, but I don't want to use hash mode for SEO related reasons.
Reference for router modes: https://router.vuejs.org/en/essentials/history-mode.html
I found a solution that works for me in this article.
To summarize the solution, I created the following 404.html file and added it to the project's root folder.
<!DOCTYPE html>
<html>
<head>
<script>
// ====================================================================================================================
// This text is simply to make sure the 404.html file is bigger than 512 bytes, else, internet explorer will ignore it.
// Thank you internet explorer for requiring such awesome workarounds in order to work properly
// ====================================================================================================================
sessionStorage.redirect = location.href;
</script>
<meta http-equiv="refresh" content="0;URL='/'">
</head>
</html>
I then added this javascript in the index.html:
(function(){
var redirect = sessionStorage.redirect;
delete sessionStorage.redirect;
if (redirect && redirect != location.href) {
history.replaceState(null, null, redirect);
}
})();
Not sure about GitLab Pages, but in GitHub Pages you can serve your whole Vue.js Application through the 404.html file instead of the index.html file. Simply rename the index.html file to 404.html file on deploy.
EDIT:
As pointed out in the comments, this has the side effect of having GitHub/GitLab serve your website with a 404 status code.
Run into same issue, found this question & tried both solution above but no luck. Then tried combine them like this:
Here my 404.html file
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<script>
// ========================================
// Credits:
// - https://stackoverflow.com/a/50259501
// - https://stackoverflow.com/a/50247140
// ========================================
const segment = 1
sessionStorage.redirect = '/' + location.pathname.slice(1).split('/').slice(segment).join('/')
location.replace(
location.pathname.split('/').slice(0, 1 + segment).join('/')
)
</script>
</head>
</html>
And here's my main.js file
const app = new Vue({
router,
store,
render: h => h(App),
created () {
if (sessionStorage.redirect) {
const redirect = sessionStorage.redirect
delete sessionStorage.redirect
this.$router.push(redirect)
}
}
})
app.$mount('#app')
And it works
https://feryardiant.github.io/static-spa/foo/bar/baz
https://feryardiant.gitlab.io/static-spa/foo/bar/baz
GitLab Answer
For those using GitLab there is now support to redirect to index.html using a _redirects file in your public folder.
Steps:
Create a file named _redirects in the public folder
Add this snippet line to that file
/* /index.html 200
Documentation: https://docs.gitlab.com/ee/user/project/pages/redirects.html#rewrite-all-requests-to-a-root-indexhtml
A little late to the party but I have a method to do this. I am using Vue CLI 3 and GitHub pages.
First of all, I commit all the source file into a source branch, and commit the dist folder (generated by Vue) to the master branch using the following shell command:
# deploy.sh
#!/usr/bin/env sh
# abort on errors
set -e
# build
echo Building. this may take a minute...
npm run build
# navigate into the build output directory
cd dist
# create a copy of index.html
cp index.html 404.html
find . -name ".DS_Store" -delete
# if you are deploying to a custom domain
echo 'custom.com' > CNAME
# remove git and reinitialise
rm -rf .git
echo Deploying..
git init
git add -A
git commit -m 'deploy'
# deploy
git remote add origin https://github.com/User/repo.github.io
git push origin master --force
cd -
rm -rf dist
When GitHub pages can't find the route, it uses 404.html. The deploy program I wrote makes a copy of index.html and names it 404.html. That's why it works.
Edit
Just realised that this wouldn't be good for SEO purposes as it returns a 404 response and Google won't index it.
You could use a 404.html hack https://github.com/rafrex/spa-github-pages/blob/gh-pages/404.html
Or you can try to pre rendering your vue into static html
https://nuxtjs.org/guide#static-generated-pre-rendering-
Based on Fery's solution, I think instead of handling redirect when creating Vue instance, the Navigation Guards could work better.
I basically added a beforeEnter guard for the index route, so that the index page will be skipped and directly go to the target page.
const routes = [
{
path: '/',
component: Index,
beforeEnter: (to, from, next) => {
if (sessionStorage.getItem('redirect') !== null) {
const redirect = sessionStorage.redirect
delete sessionStorage.redirect
next(redirect)
} else {
next()
}
}
},
]
Hope this is helpful.
2021 Solution for vue3 & vue-cli:
Follow this with "Basic instructions":
https://github.com/rafgraph/spa-github-pages#usage-instructions
no need to change var pathSegmentsToKeep = 0; the 404.html.
and then in the vue.config.js:
// do not use "./dist/"
publicPath: "/dist/",
// make the index.html file place at the root of the repo
indexPath: "../index.html",
then the spa is good to go~

ASP.NET Core's wwwroot is included in path by wiredep and gulp-inject..how can I exclude it?

We have a *.sln that includes an ASP.NET Core RC2 *.csproj for client html only (ASP.NET Controllers are in another *.csproj).
This gives the following folder/file structure:
SolutionRoot/
ClientProjectRoot/ <- project root, npm root folder
wwwroot_dev/ <- location of src dev files,
wwwroot/ <- where gulp concats, minimifies, optimises, and root of static pages
bower_packages/
node_modules/
package.json
bower.json
.bowerrc <- where 'directory' is set to 'wwwroot/bower_packages/'
gulpfile.js
Requirements I'd like to meet are:
The csproj is only client artifacts, with no asp.net C# code, so that we can give the whole project to external devs with UI expertise, and slot it back into the solution when done.
The wwwroot/index.html file should be accessible as http://example.com/index.html -- not http//example.com/wwwroot.html
CSS and JS should be minified, and in wwwroot, and html picked up from there (ie wwwroot_dev is there just for editing purposes but never served from directly).
No idea where bower packages should be -- part of this question.
The gulpfile has tasks defined, which correctly minify the css and scripts found in wwwroot_dev into app.min.js and app.min.css within wwwroot.
It's the html files, passed through gulp-inject and wiredep that get their relative pathing wrong. They both include wwwroot in the output.
My files so far are:
.bowerrc:
{
"directory":"wwwroot/bower_components"
}
And in gulpfile.js, the html task looks as follows:
gulp.task('dist:html',['dist:scripts'],function(){
//get the dest js and css that previous tasks have already minifieded:
var sources = gulp.src(
['wwwroot/scripts/**/*.js', 'wwwroot/scripts/**/*.css'],
{read:false}
);
return gulp
.src("wwwroot/scripts/**/*.html", {})
.pipe(plugins.inject(sources, {relative:true}))
.pipe(plugins.wiredep(sources,{relative:true}))
.pipe(gulp.dest("wwwroot/");
});
The output is (wrong) as it mentions wwwroot/, when it simply be ../js/ etc:
<!-- bower:js -->
<script src="../wwwroot/bower_components/jquery..."></script>
<!-- endbower -->
<!-- inject:js -->
<script src="/wwwroot/js/main.min.js"></script>
<!-- endinject -->
I serve from wwwroot:
gulp.task('serve',function(){
return gulp
.src('wwwroot')
.pipe(plugins.webserver(
{ directoryListing:false,open:"http://localhost:8000/"}))
}
I've tried lots of different inject and wiredep option flags (relative:true, ignorePath, cwd, -- but wwwroot is always mentioned. Can't get rid of it!)
So my question is...
a) is my directory structure approximately right -- or totally flawed
b) if basically right, what tweak can I do to get the paths generated by inject and wiredep to be relatively right?
Thank you!
Try this
gulp.task('render', function () {
var target = gulp.src('./Views/Shared/_Layout.cshtml');
var sources = gulp.src([path.wwwroot + "/**/*.js", path.wwwroot + "/**/*.css"], { read: false });
return target.pipe(inject(sources, {
transform: function (filepath) {
//Delete wwwroot
for (var i = 0; i < arguments.length; i++) {
if (typeof (arguments[i]) == 'string')
arguments[i] = arguments[i].replace("/wwwroot", '');
}
return inject.transform.apply(inject.transform, arguments);
}
}))
.pipe(gulp.dest('./Views/Shared'));
Had the same issue, solved it based on this solution:
https://stackoverflow.com/a/34581414
gulp.task('inject', function () {
var target = gulp.src('src/_Layout.cshtml');
return target.pipe(inject(
gulp.src(paths.wwwroot + 'css/**/*.css', { read: false }),
{
transform: function (filePath) {
var newPath = filePath.replace('/wwwroot', '');
return '<link rel="stylesheet" href="' + newPath + '"/>';
}
})
)
.pipe(gulp.dest('Views/Shared'));
});

making jquery work in expressjs app

It is a noobish question.
I am writing an expressjs app. I am not able to get jquery or bootstrap working.
// app.js
app.use(express.static(__dirname + '/public'));
Also tried
app.use(__dirname + '/public');
or
app.use(path.join(__dirname + '/public'))
or
app.set(__dirname + '/public');
or
app.set(path.join(__dirname + '/public'))
// views/home.html
<head>
<script src="/js/jquery.min.js"></script>
</head>
<body>
<script>
$(function(){
alert('hello');
});
</script>
</body>
//public>js>jquery.min.js
It is not working. I am using express 4.
Template works fine other than jquery
I have a need for this to work offline while writing this app, so can not use CDN
DIRECTORY STRUCTURE
app.js
views
--layouts
--partials
public
--js
----jquery.min.js
Using 'hbs' package, handlebars for templating
Thanks
Looks to me like you shouldn't be able to reach your view with your current setup. When you say app.use(express.static(__dirname + '/public'));, you are saying that when you hit http://{hostname}:{portNumber}, you'll be served content from the the /public folder. You shouldn't be able to access any resources on your file system that do not fall within the /public folder. So maybe if you set up a folder structure like:
app.js
--public
----views
------layouts
------partials
------home.html
----js
------jquery.min.js
that I think would work (assuming that your view.html still points to jquery.js in the folder structure correctly).

Stylus middleware in Express not working?

In app.coffee I have
stylus = require("stylus")
...
app.use stylus.middleware
debug: true
src: __dirname + "/stylus"
dest: __dirname + "/public/css"
compile: (src) ->
console.log(stylus(src))
return stylus(src)
I included the styles in layout.jade like:
link(rel="stylesheet", href="/css/styles.css")
But in Chrome network tab, I see canceled for styles.css why is that?
When I point the browser directly to /css/styles.css, I get
Cannot GET /css/styles.css
Whats wrong? How do I fix this?
Do you have the static middleware properly configured and working and positioned AFTER the stylus middleware in your middleware stack? The stylus middleware is just going to read the .styl file and write the corresponding .css file but it expects the static middleware to then find the .css file and serve it.
Also note that your src and dest file hierarchies should correspond directly. By that I mean even counting all intermediate directories if you list the recursive contents of one directory (ls -R or similar) then the ONLY difference should be src contains .styl files and dest contains exactly corresponding .css files. Don't tack a /css prefix onto one but not the other, for example.
Recently I run into the same issue and as long as #PeterLyons answer is correct I found that adding the extra slash after css directory name also seems to fix the problem.
(without coffee)
var stylus = require('stylus');
app.configure(function() {
app.use(stylus.middleware({
src: __dirname + '/stylus',
dest: __dirname + '/public/css/' // <-- additional slash after "css"
}));
app.use(express.static(__dirname + '/public'));
});
Not sure if this is stylus version-related issue and wasn't/was present before but still it's quite confusing to me.
This has been driving me crazy for a few hours so I thought I'd share :)
I serve my external files from /public
So my stylesheets are in /public/styles. All I had to do was put my .styl files in a folder called /styles in the root of my project.
modules.app.use(modules.stylus.middleware({
debug: true,
src: __dirname + '/',
dest: __dirname + '/public/',
compile: compile
}));
I got around the whacky path requirements as I'm always going to ask for styles in /styles
GET /styles/website.css serves /styles/website.styl from the root / directory of the project
this worked for my
app.use(express.static('public'));
//stylus
function compile(str, path) {
return stylus(str)
.set('filename', path)
}
app.use(stylus.middleware(
{ src:'/public/css'
, compile: compile
}
));
put your file.styl in public.css it will be compiled there too!
the problem must be the src directory, it seems you are pointed to modules/stylus, anywhere I am not an exprert but this way works