I've built my first full React app, and it works beautifully. I load my dev-server and everything loads exactly as I would hope. Notably, my image files load perfectly.
An example of a successful image load on my dev server:
<img src='./img/sq/filename.jpg' />
When running the dev server, when I inspect this element in the console and go to 'Sources', I see the file tree like this:
- localhost:3333
- css [folder]
- js [folder]
- img/sq [folder]
- filename.jpg
- index [file]
This is as I would expect.
However, when running the production server, the image fails to load. When I inspect the element, and go to 'Sources', this is what I see instead:
- localhost:3000
- static [folder]
- css [folder]
- js [folder]
- index [file]
So my production build is apparently ignoring the /img/sq folder altogether.
I've heard about file-loader and url-loader, but I've yet to find a clear and simple explanation of what they do and how to use them. I've installed both to my dependencies successfully, and I've added this loader to my webpack.config.js file:
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'file?hash=sha512&digest=hex&name=[hash].[ext]',
'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'
]
}
After doing this, I'm not sure how this is supposed to change the way the images load. Should I change the way the image is referenced? Any help/pointers would be massively appreciated, as this has me stumped.
UPDATE:
This is my server.js file. I can't see any radical difference between the code that you posted and my own, except for me using res.render method, to your res.sendFile.
Is there anything I may have missed here?
server.js
var express = require('express')
var app = express();
app.use('/static', express.static(__dirname + '/static'));
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.get('*', function (req, res) {
res.render("index");
});
const port = process.env.PORT || 3000;
const env = process.env.NODE_ENV || 'production';
app.listen(port, err => {
if (err) {
return console.error(err);
}
console.info(`Server running on http://localhost:${port} [${env}]`);
});
I recommend you using the 'Create React App' as a skeleton.
https://github.com/facebookincubator/create-react-app
You can add an image to the App.js that is created to test if the image loads in both your development and production servers.
our app class with the added image should look like this:
class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<img src='./img/sq/filename.jpg' />
</div>
);
}
}
As an example, you can successfully load an image with node.js server with this code (file index.js) and the build folder with the react code
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static('./build'));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, './build', 'index.html'));
});
app.listen(9000);
To summarize the steps are:
Use the 'Create React App' to create a skeleton for you application
Add a single image to the render code (use the above code)
Run npm run build to create the build folder with the image in it
Use the node.js code to create a server (use above code) and put your build folder (created in the previous step) next to your index.js node code.
Remark: you should install 'express' 'path' modules and then run your server node.js code.
npm install express --save
npm install path --save
node index.js
Navigate to localhost:9000 to see your app with the image in it.
These steps should help you resolve your issue as it is an example of how to build react code to be used in production and see the image in a production environment.
Related
I have a bot command which is an image scraper, and it uses puppeteer. I have the puppeteer files downloaded into my VSC(Visual Studio Code) and when I run the bot from the VSC terminal, the image scraper function works. I can commit the files that I use onto GitHub, which is then linked to Heroku. But when I try to host the bot on Heroku and use the image scraper command, Heroku gives UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process! I have also added the puppeteer buildpack to my heroku project as well, and that doesn't seem to fix the problem. One solution I've seen is adding { args: ['--no-sandbox'] } to the code, but I'm not sure where to add it. Where can I add the --no-sandbox, or is there another fix to this problem? Thanks
Image Scraper code:
var Scraper = require('images-scraper');
const google = new Scraper({
puppeteer: {
headless: true
}
})
module.exports = {
name: 'image',
description: 'sends img to channel',
async execute(client, message, args){
const image_query = args.join(' ');
let rng = Math.round(Math.random()*10)
if(!image_query) return message.channel.send('Unable to find image');
const image_results = await google.scrape(image_query, 100);
message.channel.send(image_results[rng].url);
}
}
Edit (for image-scraper)
You can use all puppeteer.launch options as normal, with the puppeteer option. You can do it like this.
const google = new Scraper({
puppeteer: {
headless: true,
args: ["--no-sandbox"],
},
});
You can read more about using image-scraper on Heroku here.
Previous (for puppeteer)
As you mentioned you can add --no-sandbox argument to your code like this.
const browser = await puppeteer.launch({
args: [
'--no-sandbox',
],
});
You can read the puppeteer.launch documentation here.
If this doesn't help you, you should check out the official troubleshooting guide on running Puppeteer on Heroku.
I'm following along this tutorial to get the vuex store in cypress while running e2e tests.
As I use vue-cli (#vue/cli 4.3.1), with the #vue/cli-plugin-e2e-cypress.
As of this setup, I don't have an app.js, rather a main.js.
But if I put the needed code in the main.js, it does not work:
/**
* Start APP
*/
const app = new Vue({
router,
render: h => h(App),
}).$mount('#app');
if (window.Cypress) {
console.log('Running in Cypress');
// only available during E2E tests
window.app = app;
} else {
console.log('NOT Running in Cypress');
}
If I run it from cypress, I doesn't log anything from main.js to the console.
In cypress, when I try to get the store
cy.window().its('app.$store')
I get the error:
Timed out retrying: cy.its() errored because the property: app does not exist on your subject.
How can I get it running with vue-cli?
I'm trying to build an app using Tone.js on top of Nuxt.js. Tone.js requires the browser's Web Audio API and as Nuxt renders stuff on the server side my build keeps failing.
Nuxt addresses this in the plugin documentation and I've followed that approach in my nuxt.config.js file writing:
module.exports = {
plugins: [{src: '~node_modules/tone/build/Tone.js', ssr: false }],
}
however that results in this error: [nuxt] Error while initializing app TypeError: Cannot read property 'isUndef' of undefined. Looking at Tone's source I'm pretty sure this is because I'm getting it because the code is still being executed on the server side.
I've seen solutions putting the js file into the static folder and checking process.browser but both result in Tone being undefined.
My question seems to be the same as this one if it's helpful additional context
Instead of import a plugin, in your page.vue you can init Tone.js in the mounted() method, because this function is run only from client-side.
Example of page/test.vue file:
<template>
<div>
Tone.js
</div>
</template>
<script>
export default {
mounted() {
var Tone = require("Tone");
var synth = new Tone.Synth().toMaster();
synth.triggerAttackRelease("C4", "8n");
}
}
</script>
I am using Angular-cli for this build and it compiles all folders under the src folder into the build.
I was storing images in the assets folder under src:
src
|-app
|-assets
|-img_library
I access them dynamically like this:
<img src="assets/img_library/{{imgId}}"
Unfortunately this folder gets compiled into the build by angular-cli, so I would have to rebuild the app every time an image is added for the client to be able to access it.
I built the server as well so I can store the images anywhere I want but I don't know how to access folders above the src via a img tag.
Is there a way to access a public/assets folder above the src folder with an image tag in Angular?
#jonrsharpe You're right this doesn't make any sense. The assets folder is for images/media that will be used often by most users. I don't know what I was thinking, my brain was stuck in Angular mode when I needed to approach it from the backend.
I used an express api:
router.get('/some/api/:id/img.png', function( req, res, next){
var id = req.params.id,
filePath = 'img.png',
root = __dirname + '/some/location/' + id +'/';
var options = {
root: root,
dotfiles: 'deny',
headers: {
'x-timestamp': Date.now(),
'x-sent': true
}
};
res.sendFile(filePath, options, (err) => {
if (err) {
next(err);
} else {
console.log('Sent:', filePath);
}
});
})
to respond to a get request from <img src='some/api/{{imageId}}/img.png'>.
Hope this helps some other sleep deprived developer.
I'am trying to run a web server and open an HTML file via gulp-connect and gulp-open.
The server is running, the html is opened correctly but not through the server but as a file from the HDD.
On the URL address bar I can see: "file:///Users/...." instead of "http://localhost:9000/"
Does anyone know what could be the issue ?
Thanks for your help
"use strict";
var gulp = require('gulp');
var gulpConnect = require('gulp-connect'); // run a local dev server
var gulpOpen = require('gulp-open'); // open a URL in the browser
var config ={
port:'9000',
baseDevUrl:'http://localhost',
paths: {
html: './src/*.html',
dist:'./dist'
}
};
// start a local development server
gulp.task('connect',function(){
gulpConnect.server({
root:['dist'],
port: config.port,
base: config.baseDevUrl,
livereload:true
});
});
gulp.task('open',['connect'],function(){
gulp.src('dist/index.html')
.pipe(gulpOpen('',{ url: config.baseDevUrl +':'+ config.port +'/', app:'google chrome'}));
});
gulp.task('html',function(){
gulp.src(config.paths.html)
.pipe(gulp.dest(config.paths.dist))
.pipe(gulpConnect.reload());
});
gulp.task('watch',function(){
gulp.watch(config.paths.html,['html']);
});
gulp.task('default',['html','open','watch']);
OK here is how you open things:
gulp.src('./index.html').pipe(gulpOpen({uri: 'http://localhost:8888', app: 'Google Chrome'}));
You've got an extra first parameter in gulpOpen and url should be uri
Good luck!