A brief introduction
First of all, I know, the question is often asked and I have read many discussion before asking.
Tipical approches to handle the cache problem that are suggested in other question are:
Versioning js files in this way: <script src="/myJavascript.js?version=4"></script>. See Keparo's answer here.
Create a rewrite rule on the web server in this way: RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]. See Kip's answer here.
Context description
Currently I'm refactoring my old php code running on apache2, introducing an heavy layer of js/jquery to handle the frontend and decoupling FE and BE building some api.
The js project is organized in this way:
my-project/
├── main.js
├── main.css
├── main.php
├── js/
│ ├── JsClass1.js
│ └── JsClass2.js
└── src/
└── php_code/
├── class1.php
└── class2.php
My problem
I don't know how to avoid that js classes are cached from web browser because the previous solution describer in the description are not feasible.
Just to make a brief example of my problem this is a portion of code that gives me problems:
main.js
//Import my js classes
import JsClass1 from './js/JsClass1.js';
import JsClass2 from './js/JsClass2.js';
//Instantiate js objects
const j1 = new JsClass1();
const j2 = new JsClass2();
//Use js object
j2.do_stuff();
j2.do_stuff();
JsClass1.js
import JsClassN from "./JsClassN.js";
export default class JsClass1 {
constructor(var1) {
//Create stuff
}
do_stuff() {
//Doing real stuff
}
}
main.php
<!DOCTYPE html>
<html lang='it-IT'>
<head>
<script type='module' src='/main.js?ver=<? echo getVersion(); ?>' type='text/javascript'></script>
</head>
<body>
...
</body>
Wrap up
How can I handle those js imports and avoid that browser caches old classes when I release in production new versions?
Do I need to reorganize my code structure to achieve this? And if so, what's the best approach?
Related
Recently, I've supporting a Laravel project that uses Laravel Mix as front-end asset bundler (CSS and JS). I've noticed that, in main JS file, the developer was used some require() rules at start, and those require() rules was referring to other JS files located in same directory, and those JS files are "normal" browser-friendly JS script (like jQuery, Bootstrap, GSAP etc). After those require() rules, the developer used normal import rules from ES6, referring to NodeJS dependencies and other modules within the project.
To better explain what I'm trying to show...
File tree:
.
└── src
├── bootstrap.js
├── components
│ ├── AnotherFeature.js
│ ├── Carousel.js
│ └── Something.js
├── jquery.js
└── main.js
The main.js file...
require("jquery");
require("bootstrap");
import {AnotherFeature} from "./components/AnotherFeature";
import {Carousel} from "./components/Carousel";
import {Something} from "./components/Something";
class Main {
constructor() {
new AnotherFeature();
new Carousel();
new Something();
}
}
new Main();
And, even using Laravel Mix (that uses Webpack), the jQuery, $ and bootstrap are available to run through browser`s console.
My question is: how can I do something like this outside Laravel Mix? I'm working on a project that uses JS, and some third-party resources aren`t ES6 modules, and I can't find a beautiful solution to use them in my project. The way Laravel Mix "import" extra JS files is a good way to fix my issues, keeping simple and all thing in one bundled JS file.
You can find my project at my GitHub. It consists in a Wordpress starter template that people want to use at my job, and this method of "requiring" and "importing" things will be very helpful.
Thanks!
I have recently been working in p5.js in the Atom ide and have been trying to use a local p5.js library downloaded from their website. As a minimal example, I have tried to execute a basic sketch.js file using the atom online web server package (atom-live-server-plus) and by referring to the p5.js library which is positioned in the parent folder of the atom project. This way I only need one copy of the p5.js library and all my numerous p5.js projects can refer to the same library without it needing to be repeated.
The issue: I have been unable to execute the code since an issue occurs when I specify the p5.js library location in the .html file using '..' syntax. Example:
<script src="..\libraries\p5.js"></script>.
Through tests I have managed identify this as an issue by finding two alternative methods to get the sketch.js file to work:
A) insert the p5.js library file into the root directory, ie the project folder (test_1) and call it directly in the .html file. Example:
<script src="p5.js"></script>
B) Call an online http: website version of the p5.js library in the.html file. Example:
<script src=https://Unpkg.com/p5></script>
In both cases the sketch.js file loads on the online server as expected.
However, I would like to understand why the syntax '..' to describe the path to a parent folder does not work especially as I have recently downloaded the Generative Design book code examples (https://github.com/generative-design/Code-Package-p5.js) which require an extensive set of libraries to run each code's own sketch.js file and therefore it is in my best interests to use the local library folder and keep it in the parent folder rather than copy it into each individual code project's directory. I, therefore, need to find a way to refer to a parent folder library in the .html file. Please could you provide any insight into my issue?
Minimal Example Code Structure:
p5_work
|
+-- libraries
| |
| +-- p5.sound.js
| |
| +-- p5.js
|
+-- test_1 (Atom project)
|
+-- index.html
|
+-- sketch.js
index.html Code:
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>p5.js test_1 example</title>
<style>
body {
padding: 0;
margin: 0;
}
</style>
<script src="..\libraries\p5.js"></script>
<script src="sketch.js"></script>
</head>
<body>
<main>
</main>
</body>
</html>
sketch.js Code:
function setup() {
createCanvas(720, 400);
background(0);
}
function draw() {
fill(255,0,0)
ellipse(50, 50, 80, 80);
}
While I am not that qualified to answer any question regard to JavaScript and P5. I tried to build a repository similar to the one I am doing always with Python then I faced this problem. Which almost made me quit the P5 learning project. After reading many and many articles I found the following:
It probably won't work. If your server setup is normal only public and
the folders below it are accessible from the client-side. From the
client's point of view, the public is the root, there is nothing above
that.
As for importing bootstrap, see if you can browse what node is making
available in your browser. It's probably hosting the scripts you need
to reference on the client-side at another URL. You might also find
the URL in the bower documentation/examples.
You could solve this by copying or symlinking the scripts into the
public directory, but that would be a bit hackish, save it for if you
get completely fed up with finding the intended way.
See more details here:
Referencing a parent directory in HTML
The best solution I found so far is based on the p5-manager npm library.
Quick Start
$ npm install -g p5-manager
There are several use case of p5-manager, Before going further, choose the one best describe your requirements and go ahead.
Step 1: Initialize a new collection
$ p5 new my_collection
By running this command, it will create a collection directory and some p5 libraries to it. See the output log:
# create : my_collection
# create : my_collection/libraries
# create : my_collection/libraries/p5.js
# ...
Step 2: Generate a p5 project
$ cd my_collection
$ p5 generate my_project
# or...
$ p5 g my_project
This will generate a p5 project folder with default templates in it. (Make sure you are running this command in a collection directory.)
# create : my_project
# create : my_project/sketch.js
# create : my_project/index.html
Step 3: Start the server and have fun!
$ p5 server
# or...
$ p5 s
Now edit your sketch.js and go to localhost:5555, then p5-manager will do the rest. The server supports live reload as default. (Notice: You should run the p5 server in a collection directory, instead of a project directory.)
More details are here:
https://www.npmjs.com/package/p5-manager
Now, I can run as many as I want of sketches that are referred to the same index.html. My previous setup was about creating multiple downloads of the P5 library for each sketch., but now I overcome this problem and the structure is ready for my P5 learning journey. I hope you will find this post helfpul.
└── Library/
│ ├──── index.html
│ └──── sketch.js
├── LICENSE
├── README.md
└── database/
└── develop/
└── libraries/
│ ├──── p5.dom.js
│ ├──── p5.js
│ └──── p5.sound.js
└── node_modules/
└── notes/
├── package-lock.json
├── package.json
└── services/
└── src/
│ ├──── index.html
│ └──── sketch.js
└── testing/
└── typescript
Last Note I promise: This issues appeared in many places, and still not solved by so many.
node.js require from parent folder
Referencing a parent directory in HTML
https://discourse.processing.org/t/p5-js-not-found-in-parent-directory/21981
The file is called p5.min.js not p5.js.
I just figured out that since I built my app with Next.js, I can't use CRA's folder structure framework to build or diagnose my application.
Unfortunately, I'm completely at a loss at the moment with respect to how Next.js applications are supposed to properly scale a website for mobile devices. I've always been under the impression that it was the job of index.html to do that (which I've written, but my app can't seem to bother to find it or use it). I've looked at the default folder structure for a Next.js app:
├── README.md
├── components
│ ├── head.js
│ └── nav.js
├── next.config.js
├── node_modules
│ ├── [...]
├── package.json
├── pages
│ └── index.js
├── static
│ └── favicon.ico
└── yarn.lock
source
but there doesn't seem to be a place for index.html.
My question is simply, how do Next.js apps optimize for mobile screens? Are they even supposed to have an index.html, and if so where? And how do favicons work, because I've created the static folder and put the favicon inside, but I'm pretty sure to have the favicon do anything, it has to be referenced by a file (conventionally index.html).
repo
Next has this Document component which you can customize to your own likings.
As their official docs say:
Is used to change the initial server side rendered document markup
You can use it to customize your head tag content as you would do anyway in your index.html.
Don't forget to add <meta name="viewport"content="width=device-width, initial-scale=1.0" /> in head tag if you want your app to use media queries.
Next project is not supposed to have a particular index.html file. Instead, the initial page is supposed to be a component located specifically in pages/index.js.
So at work we bought a theme that I have to customize and use it for an internal project. They use pug to generate the final files from some templates. In the .pug templates I can insert, of course, some external javascript files.
An empty js example for a file from them looks like this:
(function(window, document, $) {
'use strict';
$(window).on('load', function () {
})
})(window, document, jQuery);
(jQuery and bootstrap are automatically included in the templates).
I sucessfully created my javascript files and used them to work on the project using only pure js and some jQuery (however I kind of missed angularjs, but I wasn't able to use .pug and angular in the same time).
I came to the point where I had to make some multiple GET request to a server and I need them to be asynchronous. In my previous projects I successfully used the async module and I wanted to use that here too. Surprise, surprise, I can not import the module.
I tried with a simple line like import * as async from '../libs/async/async.js'; but if I want to use a simple async.series, it says: Uncaught TypeError: async.series is not a function. I tried in every way possible. The errors were varying from the one above to "Unrecognized token *". And yes, I declared the .js file as type="module".
I tried to simulate the problem in by myself and I created the following files structure (it resembles the one in the theme).
.
├── assets
│ └── js
│ ├── dashboards
│ │ └── dash.js
│ └── libs
│ └── async.js
└── src
└── index.html
In the .html file, I only include jQuery and the dash.js file. The dash.js file contains the following code:
'use strict';
import * as async from '../libs/async.js';
$(window).on('load', function () {
function init() {
console.log("Hello there!");
async.series([
function(callback) { console.log(5); callback(); },
function(callback) { console.log(6); callback(); }
]);
}
init();
});
But...errors again.
Uncaught ReferenceError: async is not defined
at init (dash.js:8)
How on earth can I import the async module (or any other module) and use it correctly?
UPDATE:
In the .html file, If I include the line
<script src="https://cdnjs.cloudflare.com/ajax/libs/async/2.6.1/async.js"></script>
it seems it works, but I really want to know if this can be done without it.
In the .pug file, changing the order of the .js files helped. I put async.js
script(src=assets_path + '/js/libs/async.min.js', type='text/javascript')
as the first line for the custom js files and it worked. No other imports were needed.
I'm writing an Electron application using ES6 and ChartJS. I have babel fully set up and works fine. So far the only way I have gotten ChartJS to work is by sticking the (CDN) javascript into my head tag. When I try to import it the ES6 way (not sure how to do so properly), or simply using var Chart = require('chartjs') I get the error that Chart is not defined.
I installed ChartJS with
npm install chartjs --save
I have tried various ways of loading the javascript but they all end up blank. Only when I uncomment the CDN it works.
How do I import and use ChartJS in an electron app?
My structure
root_folder/
├── lib/
│ ├── app.js
│ ├── plot.js
│ ├── channel.js
├── src/
│ ├── app.js
│ ├── plot.js
│ ├── channel.js
├── index.html
└── main.js
At the bottom of my index.html I simply call app.js which is the entry point for the renderer.
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js"></script>
</head>
<body>
...
</body>
<script>
require('./lib/app.js')
</script>
</html>
Edit 1:
I've run some tests and even the most simple var Chart =
require('chartjs'); in a clean file automatically instantiates the chart as a BarChart. From what I've been reading is that it has to be imported globally somehow which is what happens when it's inside a <script> tag in the head.
chart.js package is loaded from CDN in head script.
chartjs package is loaded in require.
They are different packages with different names.
Generally this should be done with
var Chart = require('chart.js');
in the place where a module should be used.
If the application is transpiled with Babel, ES module imports are translated to require in transpiled code, and require can be replaced with equivalent import statement:
import * as Chart from 'chart.js';
var chart = require(chartjs) I get the error that Chart is not
defined.
There's a few things here that need fixing. First you mentioned you were using ECMAScript 6 so change var to const. Also change require to ES6's import, and import the default package from chart js (looks like it may be just chart.
The other thing was already mentioned, you should be putting chartjs in quotes: "chartjs".
In summation, it should look something like,
import chart from 'chartjs`
After you run this line, try logging chart and you should see the chart API