The Webpack Misconception
One thing to understand upfront is that webpack
does not bundle files required through fs
or other modules that ask for a path to a file. These type of assets are commonly labeled as Static Assets, as they are not bundled in any way. webpack
will only bundle files that are require
d or import
ed (ES6). Furthermore, depending on your webpack
configuration, your project root may not always match what is output within your production builds.
Based on the electron-vue documentation's Project Structure/File Tree, you will find that only webpack
bundles and the static/
directory are made available in production builds. electron-vue also has a handy __static
global variable that can provide a path to that static/
folder within both development and production. You can use this variable similar to how one would with __dirname
and path.join
to access your JSON files, or really any files.
A Solution to Static Assets
It seems the current version of the electron-vue boilerplate already has this solved for you, but I'm going to describe how this is setup with webpack
as it can apply to not only JSON files and how it can also apply for any webpack
+ electron
setup. The following solution assumes your webpack
build outputs to a separate folder, which we'll use dist/
in this case, assumes your webpack
configuration is located in your project's root directory, and assumes process.env.NODE_ENV
is set to development
during development.
The static/
directory
During development we need a place to store our static assets, so let's place them in a directory called static/
. Here we can put files, such as JSONs, that we know we will need to read with fs
or some other module that requires a full path to the file.
Now we need to make that static/
assets directory available in production builds.
But webpack
isn't handling this folder at all, what can we do?
Let's use the simple copy-webpack-plugin
. Within our webpack
configuration file we can add this plugin when building for production and configure it to copy the static/
folder into our dist/
folder.
new CopyWebpackPlugin([
{
from: path.join(__dirname, '/static'),
to: path.join(__dirname, '/dist/static'),
ignore: ['.*']
}
])
Okay so the assets are in production, but how do I get a path to this folder in both development and production?
Creating a global __static
variable
What's the point of making this __static
variable?
Using __dirname
is not reliable in webpack
+ electron
setups. During development __dirname
could be in reference to a directory that exists in your src/
files. In production, since webpack
bundles our src/
files into one script, that path you formed to get to static/
doesn't exist anymore. Furthermore, those files you put inside src/
that were not require
d or import
ed never make it to your production build.
When handling the project structure differences from development and production, trying to get a path to static/
will be highly annoying during development having to always check your process.env.NODE_ENV
.
So let's simplify this by creating one source of truth.
Using the webpack.DefinePlugin
we can set our __static
variable only in development to yield a path that points to <projectRoot>/static/
. Depending if you have multiple webpack
configurations, you can apply this for both a main
and renderer
process configuration.
new webpack.DefinePlugin({
'__static': `"${path.join(__dirname, '/static').replace(/\\/g, '\\\\')}"`
})
In production, we need to set the __static
variable manually in our code. Here's what we can do...
index.html (renderer
process)
<!-- Set `__static` path to static files in production -->
<script>
if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
</script>
<!-- import webpack bundle -->
main.js (main
process)
// Set `__static` path to static files in production
if (process.env.NODE_ENV !== 'development') {
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}
// rest of application code below
Now start using your __static
variable
Let's say we have a simple JSON file we need to read with fs
, here's what we can accomplish now...
static/someFile.json
{"foo":"bar"}
someScript.js
(renderer
or main
process)
import fs from 'fs'
import path from 'path'
const someFile = fs.readFileSync(path.join(__static, '/someFile.json'), 'utf8')
console.log(JSON.parse(someFile))
// => { foo: bar }
Conclusion
webpack
was made to bundle assets together that are require
d or import
ed into one nice bundle. Assets referenced with fs
or other modules that need a file path are considered Static Assets, and webpack
does not directly handle these. Using copy-webpack-plugin
and webpack.DefinePlugin
we can setup a reliable __static
variable that yields a path to our static/
assets directory in both development and production.
To end, I personally haven't seen any other webpack
+ electron
boilerplates handle this situation as it isn't a very common situation, but I think we can all agree that having one source of truth to a static assets directory is a wonderful approach to alleviate developer fatigue.