I have a following folder structure
.
├── public
├──└──images
├──└── image1.png
├──└── image2.png
├── src
├── vite.config.js
└── [...]
vite.config.js
const path = require('path')
export default {
root: path.resolve(__dirname, 'src'),
server: {
port: 3000,
hot: true
},
publicDir: 'public'
}
How can I access images under public folder ? I tried this from browser
http://127.0.0.1:3000/public/images/image1.png
http://127.0.0.1:3000/images/image1.png
But it gives "Not found"
Can anybody help me ?
According to the docs here
publicDir
Directory to serve as plain static assets. Files in this directory are served at / during dev and copied to the root of outDir during build, and are always served or copied as-is without transform. The value can be either an absolute file system path or a path relative to project root.
So your publicDir must be relative to the root address you set, so you need to either change the root address to the folder above src, or change the publicDir path.
Related
Does Vite support adding a folder and its content into the final product? (Adding a folder in the dist directory)
If so, then how can I do it?
See Vite's documentation on assets:
The public Directory
If you have assets that are:
Never referenced in source code (e.g. robots.txt)
Must retain the exact same file name (without hashing)
...or you simply don't want to have to import an asset first just to get its URL
Then you can place the asset in a special public directory under
your project root. Assets in this directory will be served at root
path / during dev, and copied to the root of the dist directory
as-is.
The directory defaults to <root>/public, but can be configured via
the publicDir option.
Note that:
You should always reference public assets using root absolute path - for example, public/icon.png should be referenced in source code as /icon.png.
Assets in public cannot be imported from JavaScript.
If you move your files to the public directory, they will be included in the build. You can also configure the publicDir option to include a different folder, if you can't use the public folder.
How do I use a relative path without specifying a specific drive in my electron app? I need to use something like SRC="/FILE.HTML" so my app will work on any drive installed not just a specific location. I know ./ and ../ go to previous parent folders but how can I go a few more directories back? I've seen things like %appdir%/MAIN DIR/SUB DIR/FILE.HTML, however I'm not sure how that works? Maybe I can setup some kind of variable to use in my path like that? So far I've only been able to use direct paths to go to files in previous folder which constricts my software to a specific drive.
Example: MAIN DIR/SUB DIR/FILE.HTML
EDIT: My electron app isnt displaying my Main.html. I think it has to do with my paths but im not sure?
Using absolute paths will cause you issues, especially during / after build process. Your Electron application would be
built referencing files in the wrong directories. Relevant file reference is the way to go here.
IMPORTANT: I am seeing a lot of inconsistent directory naming and file references in your directory structure.
EG: Main.html is in your JAVASCRIPT directory. Main.js (not your application entry point) is not shown in your
directory structure. Same for your Index.css file. As a result, answering this question accurately is difficult due
to the many "norms" usually found in project structure and naming conventions. Comment to this answer fir more information / help.
Within your package.json file, the "main": "..." line is the entry point to your application. As this is
relative to your project root and your Main.js file is at your project root, your entry point will be "Main.js"
PS: "electron" doesn't need to be a dependency, only a devDependency.
package.json (project root)
{
"name": "electron.menu",
"version": "00.00.01",
"description": "Electron Menu Portable Start Menu",
"main": "Main.js"
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Armored Security Group",
"license": "MIT",
"devDependencies": {
"electron": "^19.0.6"
}
}
Within your Main.js file, the path to your index.html file, or in your case, your Main.html file, is again,
relative (this time to the Main.js file as this is the file requiring it).
Using Node's path.join([...path]); method (as you
have) will place you in good stead.
Note the use
of win.loadFile(...) instead
of win.loadURL(...)
Main.js (main process)
const { app, BrowserWindow } = require('electron');
const url = require('url');
const path = require('path');
let win
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600
});
win.loadFile(path.join(__dirname, 'ROOT.ASSETS/CODE.FILES/JAVASCRIPT/Main.html'));
return win;
}
app.on('ready', () => {
win = createWindow();
});
Lastly, within your Main.html file, all paths will be relevant to the file itself. IE: Main.html.
That said, I don't see Main.js within your ROOT.ASSETS/CODE.FILES/JAVASCRIPT directory.
Additionally, I don't see Index.css within your ROOT.ASSETS/CODE.FILES/ STYLESHEET /INDEX.STYLE directory.
PS: Place your Javascript file(s) after the closing tag of your </body> element. That way, you do not need
to defer
and your script(s) will always have a full DOM to work with (unless you need to make an update to your DOM before the
page is rendered).
ROOT.ASSETS/CODE.FILES/JAVASCRIPT/Main.html (render process)
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>Electron Menu</title>
<link rel="stylesheet" type="text/css" href="../STYLESHEET/INDEX.STYLE/Index.css" />
</head>
<body>
...
</body>
<script src="/Main.js"></script>
</html>
PS: One final note, there is no real need to have directory names or file name use upper case unless you are using
camelCase.
Update
Relative & Absolute Paths
Path reference is different between file systems and internet URL's
File Systems
For our file systems example we will use:
D:/
└── path
└── to
└── my
├── first
| └── file.txt
└── second
└── file.txt
Absolute Paths
Absolute paths are paths that refer to the whole file path. They are absolute.
D:/path/to/my/first/file.txt
D:/path/to/my/second/file.txt
Let's say are are somewhere in the D:/ drive. You could be anywhere.
To get to your "first" file you would use the full path to the first text file.
D:/path/to/my/first/file.txt
Alternatively, you could use
/path/to/my/first/file.txt
This will take you to the same location if you are already in the D:/ drive. If you are in another drive, it will take you to the absolute path in that drive instead.
To get to your "second" file you would use the full path to the second text file.
D:/path/to/my/second/file.txt
or
/path/to/my/second/file.txt
Relative Paths
Relative paths are paths that refer to a point in the file system from another point in the file system.
Let's say we open a console starting at the D:/ directory. IE: The root of the D:/ drive.
D:/
To get to your "first" file you would use the path to the first text file. The reference will always start from the current directory. In this case, it happens to be the root of the D:/ drive.
path/to/my/first/text.file
From here, to get to your "second" file, you will need to move up one directory level ../, which will take you to path/to/my. From here you then need to move down into the second directory to the second text file.
../second/file.txt
If you want to go to the root of the drive that you are currently in (without worrying about what drive you are in) use /.
/
This will take you back to:
D:/
Linux also has ./ which is used to reference a relative path.
Internet URL's
Similar to file systems, but used when referencing URL addresses.
For our Internet URL's example we will use:
www.example.com
└── path
└── to
└── my
├── cool
| └── page.html
└── other-cool
└── page.html
Absolute URL
https://www.example.com/path/to/my/cool/page.html
Relative URL
Let's navigate to another page without using the absolute URL to the other page.
../other-cool/page.html
As we are already in the cool path, this takes us up one level to my and back down through other-cool to page.html.
IE:
https://www.example.com/path/to/my/other-cool/page.html
To move up two levels from here, would would use
../../
Which would take us to
https://www.example.com/path/to
Typical Electron Folder Structure
After we finish coding our Electron application, we "build" it. Our newly "built" code must be placed in a different directory to that of our "source" code else we would overwrite our source code.
Thus we will use the dist and src names as folder names.
dist holds our distributable code. EG myApp.exe
src holds our source code.
build is often used as an intermediary to hold specific OS architecture output during the build process.
Project Root
├── build
├── dist
├── node_modules
├── src
├── tests
├── .gitignore
├── package.json
└── package-lock.json
As a personal preference, I then split my src folder into directories / files like below.
src
├── main-process
| ├── dialogs
| ├── localization
| ├── menus
| | ├── main-menu.js
| | └── tray-menu.js
| ├── preferences
| ├── windows
| | └── main-window.js
| ├── main.js
| └── preload.js
├── render-process
| ├── css
| | └── index.css
| ├── html
| | └── index.html
| ├── images
| └── js
| └── index.js
└── config.json
Therefore, a basic package.json file would refer to your main entry file main.js like this.
package.json
{
"name": "myApp",
"productName": "My cool application",
"version": "1.0.0",
"main": "src/main-process/main.js"
"scripts": {
"watch": "",
"start": "electron .",
"lint": "",
"unit-test": ",
"clean": "",
"bundle-win": "electron-packager ./ server-x --overwrite --out=build/bundles --platform=win32 --arch=all --prune=true --asar --icon='./src/render-process/images/icons/icon.png'",
"dist-win": "electron-builder --windows ",
"release": ""
},
"devDependencies": {
"electron": "^19.0.0",
"electron-builder": "^23.0.0",
"electron-packager": "^15.0.0"
}
}
Your main.js file would look like this.
main.js (main process)
const { app, BrowserWindow } = require('electron');
const url = require('url');
const path = require('path');
let win
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600
});
win.loadFile(path.join(__dirname, '../render-process/html/index.html'));
return win;
}
app.on('ready', () => {
win = createWindow();
});
And finally, your index.html file would look like this.
index.html (render process)
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>Electron Menu</title>
<link rel="stylesheet" type="text/css" href="../css/index.css" />
</head>
<body>
...
</body>
<script src="../js/index.js"></script>
</html>
html-webpack-plugin is capable of handling filename within a sub-directory. However, the default dynamic import seems to be breaking when using it in combination with subdirectory filename. I have tried setting up publicPath and output path, but such settings affect the path of all chunks. I have reproduced the issue with a minimal project below:
webpack.config.js
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new HTMLWebpackPlugin({
filename: 'example/index.html',
})
]
}
src/index.js
console.log('root loaded');
import('./part2.js').then((v) => {
console.log(v);
});
src/part2.js
console.log('part2 loaded');
The above config is correctly creating the html file with relative path main.js. Following is the generated tree structure:
dist
├── 0.js
├── example
│ └── index.html
└── main.js
1 directory, 3 files
But the dynamic chunk is loaded using the following script:
<script charset="utf-8" src="0.js"></script>
which gives an error because it searches for the 0.js as /example/0.js
Failed to load resource: the server responded with a status of 404 (Not Found)
Error: Loading chunk 0 failed.
What should be the correct method to ensure that dynamic imports are correctly loaded?
I would like to set the path of the node_modules directory within the gruntfile.js. I would like to have one central node_module directory for all my grunt projects.
Is it possible to set the path for an external node_module directory?
Current setup (which works)
projekt1
--gruntfile.js
--package.json
--node_modules
projekt2
--gruntfile.js
--package.json
--node_modules
Set up which I would like to have
node_modules
project1
--gruntfile.js
--package.json
project2
--gruntfile.js
--package.json
You can.... I have been using this setup without any issues. In each of your project Gruntfile.js files, simply set the base to one directory up like so:
Given a folder structure like this:
node_modules
project1
app.js
Gruntfile.js
package.json
Your Gruntfile.js may look something like this
module.exports = function(grunt) {
// Tell grunt where to find node_modules
// This is the line you're looking for
grunt.file.setBase('../');
// Your normal grunt config
grunt.initConfig({
// Your package.json file is now relative to the parent folder
pkg: grunt.file.readJSON('project1/package.json'),
// I use webpack, your tasks will probably be different
webpack: {
options: {},
build: {
// Paths are now resolved from the upper folder
// since we set the base path to one level up
entry: './project1/app.js',
output: {
// Again, the path must be relative to the parent folder
path: 'project1',
filename: 'app.min.js'
}
}
}
// etc...
});
// Load tasks...
}
Once you setBase('../') you'll need to make sure that all your file paths are resolved correctly since your base path has been changed to 1 level up.
A warning... if you publish or distribute your package, Grunt tasks won't work for those who download it because they more than likely won't have the same setup with node_modules 1 level up. And even if they do, they may not name the project1 folder the same
Webpack docs state that output.publicPath is:
The output.path from the view of the JavaScript.
Could you please elaborate on what this actually means?
I use output.path and output.filename to specify where Webpack should output the result, but I’m not sure what to put in output.publicPath and whether it is required.
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js",
publicPath: "What should I put here?"
}
}
output.path
Local disk directory to store all your output files (Absolute path).
Example: path.join(__dirname, "build/")
Webpack will output everything into localdisk/path-to-your-project/build/
output.publicPath
Where you uploaded your bundled files. (absolute path, or relative to main HTML file)
Example: /assets/
Assumed you deployed the app at server root http://server/.
By using /assets/, the app will find webpack assets at: http://server/assets/. Under the hood, every urls that webpack encounters will be re-written to begin with "/assets/".
src="picture.jpg" Re-writes ➡ src="/assets/picture.jpg"
Accessed by: (http://server/assets/picture.jpg)
src="/img/picture.jpg" Re-writes ➡ src="/assets/img/picture.jpg"
Accessed by: (http://server/assets/img/picture.jpg)
When executed in the browser, webpack needs to know where you'll host the generated bundle. Thus it is able to request additional chunks (when using code splitting) or referenced files loaded via the file-loader or url-loader respectively.
For example: If you configure your http server to host the generated bundle under /assets/ you should write: publicPath: "/assets/"
the publicPath is just used for dev purpose, I was confused at first time I saw this config property, but it makes sense now that I've used webpack for a while
suppose you put all your js source file under src folder, and you config your webpack to build the source file to dist folder with output.path.
But you want to serve your static assets under a more meaningful location like webroot/public/assets, this time you can use out.publicPath='/webroot/public/assets', so that in your html, you can reference your js with <script src="/webroot/public/assets/bundle.js"></script>.
when you request webroot/public/assets/bundle.js the webpack-dev-server will find the js under the dist folder
Update:
thanks for Charlie Martin to correct my answer
original: the publicPath is just used for dev purpose, this is not just for dev purpose
No, this option is useful in the dev server, but its intention is for asynchronously loading script bundles in production. Say you have a very large single page application (for example Facebook). Facebook wouldn't want to serve all of its javascript every time you load the homepage, so it serves only whats needed on the homepage. Then, when you go to your profile, it loads some more javascript for that page with ajax. This option tells it where on your server to load that bundle from
filename specifies the name of file into which all your bundled code is going to get accumulated after going through build step.
path specifies the output directory where the app.js(filename) is going to get saved in the disk. If there is no output directory, webpack is going to create that directory for you.
for example:
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js"
}
}
This will create a directory myproject/examples/dist and under that directory it creates app.js, /myproject/examples/dist/app.js. After building, you can browse to myproject/examples/dist/app.js to see the bundled code
publicPath: "What should I put here?"
publicPath specifies the virtual directory in web server from where bundled file, app.js is going to get served up from. Keep in mind, the word server when using publicPath can be either webpack-dev-server or express server or other server that you can use with webpack.
for example
module.exports = {
output: {
path: path.resolve("./examples/dist"),
filename: "app.js",
publicPath: path.resolve("/public/assets/js")
}
}
this configuration tells webpack to bundle all your js files into examples/dist/app.js and write into that file.
publicPath tells webpack-dev-server or express server to serve this bundled file ie examples/dist/app.js from specified virtual location in server ie /public/assets/js. So in your html file, you have to reference this file as
<script src="public/assets/js/app.js"></script>
So in summary, publicPath is like mapping between virtual directory in your server and output directory specified by output.path configuration, Whenever request for file public/assets/js/app.js comes, /examples/dist/app.js file will be served
You can use publicPath to point to the location where you want webpack-dev-server to serve its "virtual" files. The publicPath option will be the same location of the content-build option for webpack-dev-server. webpack-dev-server creates virtual files that it will use when you start it. These virtual files resemble the actual bundled files webpack creates. Basically you will want the --content-base option to point to the directory your index.html is in. Here is an example setup:
//application directory structure
/app/
/build/
/build/index.html
/webpack.config.js
//webpack.config.js
var path = require("path");
module.exports = {
...
output: {
path: path.resolve(__dirname, "build"),
publicPath: "/assets/",
filename: "bundle.js"
}
};
//index.html
<!DOCTYPE>
<html>
...
<script src="assets/bundle.js"></script>
</html>
//starting a webpack-dev-server from the command line
$ webpack-dev-server --content-base build
webpack-dev-server has created a virtual assets folder along with a virtual bundle.js file that it refers to. You can test this by going to localhost:8080/assets/bundle.js then check in your application for these files. They are only generated when you run the webpack-dev-server.
in my case,
i have a cdn,and i am going to place all my processed static files (js,imgs,fonts...) into my cdn,suppose the url is http://my.cdn.com/
so if there is a js file which is the orginal refer url in html is './js/my.js'
it should became http://my.cdn.com/js/my.js in production environment
in that case,what i need to do is just set publicpath equals http://my.cdn.com/
and webpack will automatic add that prefix
There are lots of good answers here, so I'll focus on output.publicPath: 'auto'.
Say when you build your project you get the next folder structure:
dist/blog/index.html
dist/app.js
dist/app.css
dist/index.html
In this case, both our index.html files have to have a correct path to our app.js and app.css (next - assets). Let's consider the next scenarios:
publicPath: '' or publicPath: '/':
When hosted on a server both point to the root of the website (ex. https://localhost:8080/), so everything works fine.
But should you try to open them locally, blog/index.html won't have a correct path to the assets. In case of publicPath: '' assets will be searched in the blog/ folder since that's where the relative path is pointing to. index.html still has the correct path to assets.
And in case of publicPath: '/', / points to the root of the filesystem, so neither of our index.html files will have a correct path to assets.
publicPath: 'auto':
In this case, both our index.html files will have relative paths to the assets. So, blog/index.html will be pointing to ../app.css, and index.html will be pointing to app.css.
The webpack2 documentation explains this in a much cleaner way:
https://webpack.js.org/guides/public-path/#use-cases
webpack has a highly useful configuration that let you specify the base path for all the assets on your application. It's called publicPath.
publicPath is used by webpack for the replacing relative path defined in your css for refering image and font file.