Open t1mmen opened 8 years ago
I think we should not include web stuff into this boilerplate, it will increase unnecessary complexity in a desktop-only application. But if someone is interested in how to build them together, I can work on a separate repo to demo it in next couple of weeks.
@chentsulin Makes sense to keep it separate for complexities sake. I'd be very interested in a demo of how to, though!
I'd be very interested in this as well. @chentsulin Let me know if you decide to do this. I'm going to see if I can get it to work on my own but any help from anyone would be much appreciated. Shoot me an email @ alex.hawkins@shiphawk.com
Yo @chentsulin, I'm currently working with your boilerplate, it awesome, thank you. I'll need website build feature in next two weeks, so if I can help you somehow with it, please tell me.
I'm doing this with a modified version of this boilerplate.
All i had to do was handle argv from make-webpack-config, and when 'web' is provided then the webpack options.target = web, otherwise the electron renderer as this boilerplate provides.
Deployment is another matter - I just adapted the package.json scripts to a makefile and deploy the web version to s3 (after running a build-web using --target web as described above).
It's actually not very complicated at all. The only thing I have left to is find some way to allow the renderer process to detect whether its being run in electron or in the web, so that for example 'openDialog' function can choose to open a native dialog or material ui dialog.
The one thing that will get you caught is what build you're running in development depending on whether you are developing for electron or web, and same for deployment. Oh and make sure hot-dev-server knows what it needs to do as well.
Apologies, I forked this project a few months ago and the webpack config has changed significantly since then. I hope that this still helps folks who are looking to get this working!
https://gist.github.com/flywithmemsl/0d9eba3c7e0ebc3dddc3 — works for me
replaced commonjs2
with var
in libraryTarget
removed webpackTargetElectronRenderer
Cool! Also forgot to mention, i just passed --target web to wepback-dev-server/wepback, no argv handling
From my makefile:
build-web:
@node_modules/.bin/webpack --config webpack/webpack.config.production.js --progress --profile --colors --target web
build:
@node_modules/.bin/webpack --config webpack/webpack.config.production.js --progress --profile --colors
hot-dev-web:
@node_modules/.bin/webpack-dev-server --config webpack/webpack-hot-dev-server.config.js --hot --progress --colors --port 2992 --inline --target web
if you specify --target to webpack-dev-server or webpack, it overrides the webpack options.target prop.
This assumes you have the webpackTargetElectronRenderer set as the options.target in your webpack config.
I can confirm that @acao's approach works fine. Thanks!
Another thing to keep in mind: Polyfills weren't set up by default when I cloned this project, so you might want to include that when building for the web (assuming you're using ES6/7 features)
In the webpack config, change:
config.entry = './app/index'
... to...
config.entry = ['babel-core/polyfill', './app/index'];
Thanks a lot for your research, guys. I will try to add web support to my project this week.
I'm just wondering if the solution is to create webpack target and introduce a way to detect the environment (browser/electron) it might be worth adding right to the core or at least transform this discussion into a simple docs page? I can probably help with that if @chentsulin would be interested :)
Hello :), The compilation work well, but I don't know how to use the files int dist/. How do I connect to the web app with my browser ? with localhost:2992 it's bring me to a file explorer of my project :/
I'm waiting for the update, thanks a lot for your work :)
Were you able to make that separate repo @chentsulin? Instructions seem unclear now. Seems like the structure has changed considerably
there hasnt been any progress on this yet
0 o, No one can give a simple solution?
I haven't looked into it too much yet.
@doulmi I'd recommend for using nativefier to create a new web app runs on both env. It's the simplest way that I could ever find.
I'm sorry, but that is a terrible solution.
Have anyone done this task successfully yet ?
@vjtc0n not yet. I'm thinking of integrating react-boilerplate
into this repo just to see how portability of web -> electron is
@amilajack Thank you.
Hoping your work going well soon.
I got it working in my app last summer, by making a custom webpack config for a web build. My specific solution, provided as-is (you definitely need to alter this for yourself): https://gist.github.com/marekhrabe/4a412d232d6c9f2a25d594d2a83e6ba1
Tips for integrating to your app:
cross-env NODE_ENV=production node -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.web.js --progress --profile --colors
)node
section of the config if they fail to loadI'm not sure there is a universal solution that can be added to a boilerplate, it really depends on your app.
Has anyone got this working with the current version of the boilerplate? I attempted both @acao's solution of overriding the target to web and @marekhrabe's solution of a custom web config that does the same thing in a config file. I additionally modified the template HTML to directly import the style.css and bundle.js directly, without considering process.ENV.
Both approaches result in:
es6.number.constructor.js:20 Uncaught ReferenceError: module is not defined
The project/tooling has otherwise thus far been a dream to work with!
@lion19 At the moment, I don't think there's a proven or recommended way of doing this.
@amilajack Got it, thanks for the response. It does make sense to keep the web tooling separate. I'll be sure to post here if I come up with something helpful!
It does make sense to keep the web tooling separate.
I actually think that there should be a way to do this. Its just that no one has really come up with a proven way of doing this. Also the tooling for electron and the browser are almost identical. The only difference is the target in the webpack config. Let me know if you find anything
@amilajack I eventually did a web build working. I built a web config importing the production config. Relative to the production config I overrode the 'target' of to 'web', and additionally overrode the output.libraryTarget to 'umd' (the base config sets this to 'commonjs2'), which, if I'm not mistaken, took care of the definition of 'module' in the global scope. Additionally, I overrode the config for the HtmlWebpackPlugin to use a a separate template with web-ready references to the bundle and stylesheet.
@lion19 Would it be possible to share your webpack configs? I'd love to help find better solutions to this for myself and other users of the boilerplate.
Sure @Slapbox, here's the the web config. I haven't factored or anything, it could very likely just merge the couple properties that differ onto the production config if that makes sense for you. My custom webapp.html additionally needs to remove references to the process environment. Let me know how it goes!
@lion19 thanks so much for sharing that! I won't get to that task for a couple weeks, but I'm excited to try and really thankful to have something to help guide me.
Will definitely update when I can.
Just wanted to mention there is at least one other boilerplate out there that is attacking this issue.
Forgot to include the link....
@lion19 do you have any updated version of this config? I know a good deal has changed in the past year and I'm hoping to take a crack at this later this month. If you've got any starting point for me that's further along, I'd love to use it to try and find a config general enough to warrant a pull request.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@Slapbox Have your worked on this recently?
I did eventually reach a working solution. Unfortunately I can't share it though as my project hardly resembles the boilerplate in any way anymore, and frankly, I'm not even sure the full extent of the changes it required anymore. There were changes to a number of config files.
Here's some things I know you need to do:
First: Make a new webpack.config file for web and associated commands in the package.json file.
Second: Ensure you're not loading any dependencies which won't work on the web, such as node
's fs
or any native dependencies.
Here's some bits you'll need in your new webpack.config for web (Webpack 4). Obviously some parts of them can change, but things like libraryTarget
and target
are essential:
target: 'web',
output: {
path: path.join(__dirname, '../app/webdist'),
publicPath: './webdist/',
filename: 'web.prod.js',
libraryTarget: 'umd',
},
Sorry I don't have a ready-made solution to share. I'm happy to answer any questions you have as you try to make this work for your project though.
Thanks @Slapbox for pointing libraryTarget: 'umd'
, as I was stuck with Uncaught ReferenceError: module is not defined
error and did not understand from the docs what this attribute was made for.
My app is now working with Webpack's devServer in dev mode, and served by Apache when build.
Here's a comprehensive tutorial in case someone else is stuck:
package.json:
"dev-web": "cross-env START_HOT=1 node -r babel-register ./internals/scripts/CheckPortInUse.js && cross-env START_HOT=1 yarn start-web-dev",
"start-web-dev": "cross-env NODE_ENV=development node --trace-warnings -r babel-register ./node_modules/webpack-dev-server/bin/webpack-dev-server --config webpack.config.web.dev.js",
webpack.config.web.dev.js:
before()
hooktarget: 'web'
and add output.libraryTarget: 'umd'
as pointed out by @Slapbox open: true
to automatically open Chrome's window on http://localhost:1111/#/package.json:
"build-web": "cross-env NODE_ENV=production node --trace-warnings -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.web.prod.js --colors",
webpack.config.web.prod.js:
new HtmlWebpackPlugin({
hash: true,
title: 'My Web application',
myPageHeader: 'Hello World',
template: './app/index.template.html',
filename: '../www/index.html' //relative to root of the application
})
Nice work!
@Germain-Italic this would be a great thing to add to the wiki, maybe? then this issue can have some resolution after all these years!
@acao I'd gladly do it but there is a new problem I can't figure out. Thus it may not be related to the boilerplate itself, because it comes from HtmlWebpackPlugin versus Hotreload.
It starts normally:
PS C:\Users\Germain\Sites\presentations> yarn dev-web
yarn run v1.9.4
$ cross-env START_HOT=1 node -r babel-register ./internals/scripts/CheckPortInUse.js && cross-env START_HOT=1 yarn start-web-dev
$ cross-env NODE_ENV=development node --trace-warnings -r babel-register ./node_modules/webpack-dev-server/bin/webpack-dev-server --config webpack.config.web.dev.js
Starting Web Process...
i 「wds」: Project is running at http://localhost:1111/
i 「wds」: webpack output is served from http://localhost:1111/dist
i 「wds」: Content not from webpack is served from C:\Users\Germain\Sites\presentations\dist
i 「wds」: 404s will fallback to /index.html
i 「wdm」: wait until bundle finished: /dist
i 「wdm」:
i 「wdm」: Compiled successfully.
i 「wdm」: Compiling...
But as soon as I edit a file inside the app/ folder:
C:\Users\Germain\Sites\presentations\node_modules\html-webpack-plugin\lib\compiler.js:111
content: childCompilation.assets[outputName].source()
^
TypeError: Cannot read property 'source' of undefined
at childCompiler.runAsChild (C:\Users\Germain\Sites\presentations\node_modules\html-webpack-plugin\lib\compiler.js:111:56)
at compile (C:\Users\Germain\Sites\presentations\node_modules\webpack\lib\Compiler.js:296:11)
at hooks.afterCompile.callAsync.err (C:\Users\Germain\Sites\presentations\node_modules\webpack\lib\Compiler.js:553:14)
at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\Users\Germain\Sites\presentations\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:24:12), <anonymous>:15:1)
at AsyncSeriesHook.lazyCompileHook [as _callAsync] (C:\Users\Germain\Sites\presentations\node_modules\webpack\node_modules\tapable\lib\Hook.js:35:21)
at compilation.seal.err (C:\Users\Germain\Sites\presentations\node_modules\webpack\lib\Compiler.js:550:30)
at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\Users\Germain\Sites\presentations\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:24:12), <anonymous>:6:1)
at AsyncSeriesHook.lazyCompileHook [as _callAsync] (C:\Users\Germain\Sites\presentations\node_modules\webpack\node_modules\tapable\lib\Hook.js:35:21)
at hooks.optimizeAssets.callAsync.err (C:\Users\Germain\Sites\presentations\node_modules\webpack\lib\Compilation.js:1294:35)
at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\Users\Germain\Sites\presentations\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:24:12), <anonymous>:6:1)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
The only solution I found was to change:
new webpack.HotModuleReplacementPlugin({
multiStep: true
}),
To false
. But of course Hot reload requires a manual refresh in the browser.
Have you (or @Slapbox) encountered this error?
webpack.config.web.dev.js is here
Edit:
I almost have it. I used the process @Germain-Italic stepped through for dev., including the webpack.config.web.dev.js file and it works great! I love it!
Note: import htmlLoader from 'html-loader';
doesn't seem to be used.
However, I'm still struggling with the build part. It builds (so it seems), but I'm not clear how to deploy it. I've tried serving it a few different ways with http-server
but the best I manage to get is
console: GET http://localhost:8080/ [HTTP/1.1 200 OK 2ms]
console: GET http://localhost:8080/dist/web.prod.js?cbf9d1a283858d08c31a [HTTP/1.1 404 Not Found 1ms]
@dbvrac could you post your prod webpack.config.prod.js?
On a second read: keep in mind that after build stage, neither Webpack nor Node provide any webserver that would serve your static built files.
Am a using an Apache virtualhost pointing into my ~/project/dist/web
folder to serve them, index.html being generated by HtmlWebpackPlugin using index-web.html template (my html template is a bit different for the Electron app and for the web for some reason).
Is that what you are trying to achieve?
I haven't tried using Apache, and it isn't really my goal but if it works I'll use it. In the mean time, some context: MacOS 10.13.6, Node v10.12.0, npm 6.4.1, yarn 1.10.1, and I'm still using v0.14.0 of ERB.
My webpack.config.web.prod.js file is hosed, I'm sure.
When I run yarn run build-web
I'm not getting a ~/project/dist/
folder. I'm getting ~/project/app/dist/
and ~/project/app/www/
folders. Can you post your working version?
Here's what I've been working with. I've fiddled with it in different ways to no avail:
import path from 'path';
import webpack from 'webpack';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import merge from 'webpack-merge';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import UglifyJSPlugin from 'uglifyjs-webpack-plugin';
import baseConfig from './webpack.config.base';
import CheckNodeEnv from './internals/scripts/CheckNodeEnv';
CheckNodeEnv('production');
export default merge.smart(baseConfig, {
devtool: 'source-map',
mode: 'production',
target: 'web',
entry: './app/index',
output: {
path: path.join(__dirname, 'app/dist'),
publicPath: './dist/',
filename: 'web.prod.js'
},
module: {
rules: [
// Babel loader
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
plugins: [
// Here, we include babel plugins that are only required for the
// renderer process. The 'transform-*' plugins must be included
// before react-hot-loader/babel
'transform-class-properties',
'transform-es2015-classes',
'react-hot-loader/babel'
]
}
}
},
// html-loader
{
test: /\.(html)$/,
use: {
loader: 'html-loader'
}
},
// css-loader (global)
{
test: /\.global\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
}
]
},
// css-loader (others)
{
test: /^((?!\.global).)*\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
importLoaders: 1,
localIdentName: '[name]__[local]__[hash:base64:5]'
}
}
]
},
// SASS support - compile all .global.scss files and pipe it to style.css
{
test: /\.global\.(scss|sass)$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader'
}
]
},
// SASS support - compile all other .scss files and pipe it to style.css
{
test: /^((?!\.global).)*\.(scss|sass)$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
importLoaders: 1,
localIdentName: '[name]__[local]__[hash:base64:5]'
}
},
{
loader: 'sass-loader'
}
]
},
// WOFF Font
{
test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff'
}
}
},
// WOFF2 Font
{
test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff'
}
}
},
// TTF Font
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/octet-stream'
}
}
},
// EOT Font
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: 'file-loader'
},
// SVG Font
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'image/svg+xml'
}
}
},
// Common Image Formats
{
test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/,
use: 'url-loader'
}
]
},
optimization: {
minimizer: [
new UglifyJSPlugin({
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
map: {
inline: false,
annotation: true
}
}
})
]
},
plugins: [
/**
* Create global constants which can be configured at compile time.
*
* Useful for allowing different behaviour between development builds and
* release builds
*
* NODE_ENV should be production so that modules do not perform certain
* development checks
*/
new webpack.EnvironmentPlugin({
NODE_ENV: 'production'
}),
new MiniCssExtractPlugin({
filename: 'style.css'
}),
new BundleAnalyzerPlugin({
analyzerMode:
process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled',
openAnalyzer: process.env.OPEN_ANALYZER === 'true'
}),
new HtmlWebpackPlugin({
hash: true,
title: 'My Web application',
myPageHeader: 'Hello World',
template: './app/index.template.html',
filename: '../www/index.html' // relative to root of the application
})
]
});
HI @dbvrac sorry I couldn't reply before. The file works with Webpack latest!
It builds (so it seems)
Yes indeed, I'm getting the compiled files in the dist folder.
but I'm not clear how to deploy it
Confirmed, the files are for the web (which was my goal when I posted the example) so you can serve them using Apache or Nginx (I'm using Laragon on Windows with the built-in Apache server, and Apache on Ubuntu in production). So here's your web app.
For the Electron app, using the task "app:release" inside package.json (shortcut for yarn app:build && electron-builder
), electron-builder creates an .exe inside release/app using the following config files :
# electron-builder.json
{
"appId": "cartable.digital.app",
"productName": "Presentations Colissimo",
"copyright": "Groupe La Poste",
"directories": {
"buildResources": "src",
"output": "release/app"
},
"win": {
"target": "portable"
}
}
electron-webpack.json
{
"title": "Presentations Colissimo",
"customTemplateFile": "src/templates/structure.html",
"main": {
"sourceDirectory": "src/electron-webpack"
},
"renderer": {
"sourceDirectory": "src"
}
}
Please note that I have edited electron-webpack in order to introduce the new customTemplateFile variable. I haven't been able to merge these edits in the project due to lack of knowledge on project contribution, however I have posted all the diffs in this issue: https://github.com/electron-userland/electron-webpack/issues/197.
@Germain-Italic Thanks for the info. Which version of ERB are you working with?
Setting aside my n00b issues with Build
for a moment, I had Dev
running quite nicely. However, this was when my project was based on ERB v0.14.0. I have since brought my project up to v0.17.0 and I'm unable to get Dev
to work. I updated the scripts in package.json to look in the new configs
directory, but I'm uncertain how to get past this:
$yarn run dev-web
yarn run v1.10.1
$ cross-env START_HOT=1 node -r babel-register ./internals/scripts/CheckPortInUse.js && cross-env START_HOT=1 yarn start-web-dev
/Users/username/directory/project-name/node_modules/babel-register/node_modules/babel-core/lib/transformation/file/index.js:558
throw err;
^
SyntaxError: /Users/username/directory/project-name/internals/scripts/CheckPortInUse.js: Unexpected token (6:12)
4 |
5 | (function CheckPortInUse() {
> 6 | const port: string = process.env.PORT || '1212';
| ^
7 |
8 | detectPort(port, (err: ?Error, availablePort: number) => {
9 | if (port !== String(availablePort)) {
at Parser.pp$5.raise (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:4454:13)
at Parser.pp.unexpected (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:1761:8)
at Parser.pp$1.parseVar (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:2342:12)
at Parser.pp$1.parseVarStatement (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:2169:8)
at Parser.pp$1.parseStatement (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:1861:19)
at Parser.pp$1.parseBlockBody (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:2268:21)
at Parser.pp$1.parseBlock (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:2247:8)
at Parser.pp$3.parseFunctionBody (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:4235:22)
at Parser.pp$1.parseFunction (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:2386:8)
at Parser.pp$3.parseFunctionExpression (/Users/username/directory/project-name/node_modules/babylon/lib/index.js:3760:17)
error Command failed with exit code 1.
Hi @dbvrac my version is v0.14.0 I won't risk trying another version.
Hello friends, please see the changes required to enable web dev and production in a clean way for the latest release 0.17.
I have created PR for the same. Meanwhile, you can see the changes here. https://github.com/electron-react-boilerplate/electron-react-boilerplate/pull/2136
Hello, now the project has moved quit a bit since this discussion started. We can now run the boilerpate within the browser by default for development.
Is anyone now able to do the same within production? ( maybe with express ) So one .exe / .appimage that when installed runs the electron app, and host the same UI on localhost.
If I use ant Design, the packaged application route cannot work
I'm looking to publish my app both to the web, and as a standalone executable.
Is anyone doing this, and if so, care to share your preferred approach? If not, is this something the maintainers are interested in as part of the repo? I'll try to lend a helping hand in the coming weeks if so.