I want to write a Chrome App, but I also want to inter-op with some .Net code using Edge.js. Now I've tried it out in a Nodejs app, but am unable to figure out how to do it in a Chrome App.
I've watched the YouTube video of Paul Kinlan (the Chrome Apps office hours - NodeJS in chrome packaged apps), but can't get the code to run. I've also tried browserify with no success.
Is there a working sample which uses any of the node modules in a Chrome App (because the available resources look to be older).
Thanks in advance,
Manoj.
I've run code written for node.js inside a chrome packaged apps, and have used modules published to npm, using either browserify or webpack.
The only real tricky bit for me traditionally has been exporting functionality for use by my web app, since you don't have access to require(). I usually just create a special module that exports all global symbols I want to access and use that as my entry point.
E.g., using webpack, I'd create a file called globals.js:
module.exports = exports = {
a: require('a'),
b: require('b'),
...
}
Then create a webpack.config.js:
module.exports = {
context: __dirname + "/js",
entry: {
globals: [
"globals.js",
],
},
output: {
// Make sure to use [name] or [id] in output.filename
// when using multiple entry points
path: __dirname + "/js/generated",
filename: "[name].bundle.js",
chunkFilename: "[id].bundle.js",
library: "[name]",
libraryTarget: "umd",
}
};
Then I can pack that and include the generated bundle in my application, and use the global variable globals now.
I am not sure Edge.js works, but I would not consider it likely that it will be possible to webpack/browserify that into a web/chrome app, because their is no support for native bindings, and inter-process communication is a lot different. I'm just not sure how it could work.
(But you can probably implement your own interop with .net applications using a different kind of IPC, perhaps)
Related
I have a library of Java code from Android development and I'd like to reuse that in a web-app version of the same. The library code is quite generic as it was always intended to be re-usable and has, in the past, been used to generate Android/Java, App-Engine/Java, iOS/ObjC, and GWT apps.
Looking around, I think the best framework for the web app would be Angular. Rewriting the library code to Kotlin should be a relatively minor task as there are tools to do most of the work. Then it can be compiled for the JVM (for native and backend apps) or JavaScript (for web apps).
While advice for/against this plan is welcome, my actual question is...
How do I set up an IntelliJ project to do this?
I thought the obvious answer would be two modules: one for the lib and one for the app but IntelliJ doesn't allow creating a Kotlin module, only a Kotlin project.
Instead, I made a Kotlin/JS project and used Angular/CLI to create the app module beneath it (with a backend app to sit beside it sometime in the future). The library builds and the sample app runs but I haven't been able to get the latter to include the generated JS (plus .d.ts) code of the former which sits in some deep directory under build/. So maybe I'm going about it all wrong...
Wow, that was rough! After many hours of Google searches and attempts that failed, here is something that works. Perhaps I'll find cleaner methods down the road but this is acceptable for now.
Note: I wasted too much time on gradle plugins for my liking. If they're not first-party, they tend to be unmaintained, poorly documented (largely assuming that the reader already knows what they're doing), and out of date. What follows is done only with first-party support programs.
Create a top-level project with Angular/CLI followed by sub-projects for the app and library:
ng new MyGeneralProject --no-create-application
ng generate library klib
ng generate application MyApp
Now set up Gradle in the top-level directory (or wait and do this via the IDE):
gradle init
gradle wrapper
Open the top-level in IntelliJ. Create/edit the top-level build.gradle.kts file:
buildscript {}
plugins {}
repositories {}
More important is the top-level settings.gradle.kts file:
rootProject.name = "MyProject"
include("projects:klib")
This will now access the projects/klib/gradle.build.kts file:
plugins {
kotlin("js") version "1.8.0"
}
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib-js"))
testImplementation(kotlin("test-js"))
}
kotlin {
sourceSets {
all {
// allow #JsExport without opt-in each time
languageSettings.optIn("kotlin.js.ExperimentalJsExport")
}
val main by getting {
kotlin.srcDir("src/main")
}
val test by getting {
kotlin.srcDir("src/test")
dependencies {
implementation(kotlin("test"))
}
}
}
js(IR) {
moduleName = "klib"
browser {
distribution {
directory = File("$projectDir/../../dist/$moduleName")
}
}
binaries.library()
}
}
The above uses the kotlin("js") plugin for Gradle but that's provided by JetBrains as part of IntelliJ who also maintain the Kotlin language libraries. Though the documentation for it also assumes you already know everything about Gradle, it nonetheless works just fine.
The built JS/TS library will be created under the top-level directory as "dist/klib". This naming could use some improvement but it's a reasonable starting point.
In the top-level tsconfig.json file, under "compilerOptions", look for "paths" and update as desired. I went with a leading "#" to indicate a top-level import location:
{
...
"compilerOptions": {
...
"paths": {
"#klib": [
"dist/klib"
]
}
...
},
...
}
In the projects/myapp/src/app/whatever.ts file, access the converted Kotlin library:
import * as klib from '#klib'
Then the entire library is available as klib.blah.blah.blah with IntelliJ providing full completion semantics.
2023-02-07: I've found that while this approach worked okay for creating the desired Angular project, it fell apart when trying to add a jvm-based backend with which it shared code. Now trying a different tactic...
I have a very old javascript code base and I do not want to use the modern way of compiling all of the javascript files into one using standard webpack because it is not possible due to the way the website code is written.
But I want to write new scripts using modern Javascript (e.g. Promises and Fetch) but still be able to support old browsers like IE11.
I have configured webpack and babel so it gets multiple entry javascript files and for each of them it does the classic transpiling/polyfilling using #babel/preset-env and corejs.
This works and polyfills every script based on the babel target config but it creates one issue. It encapsulates global variables/functions in the script so they are not accessible from other scripts which reference them (yes old javascript). Is there a way to disable this structural modifications?
Also I know I could use only Babel without Webpack for this but the problem is when I try to polyfill e.g. Fetch I have to use https://github.com/github/fetch which cannot be just used with Babel afaik.
Any help appreciated.
I think inevitably your refactorings are modernizing the code, and if you are not careful, one day you can end up bundling everything with webpack;)
The set up you describe, I achieved with with:
module.exports = {
entry: {
messages: "./src/messages",
"hello-world": "./src/hello-world",
},
output: {
library: {
type: "global",
},
filename: "[name].js",
},
};
every export from each file is put directly on window - if you load files in the right order, you can have invisible dependencies maintained across the codebase.
To this setup, you can add babel loader with presets as you stated in your question. Besides, you can tart doing the explicit imports across different files - even if function X is available on global scope, you can migrate some places to import/require it explicitly.
If you want to play with my code yourself, you can find it here:
https://github.com/marcin-wosinek/webpack-legacy/
and here is the example in action:
https://marcin-wosinek.github.io/webpack-legacy/
I am building an isomorphic package where I am using a flag in various files to detect if we are in the browser or in node. If in node, I require an internal package ie if (isNode) { require("/.nodeStuff) } that has as one of its dependencies the fs module. However, webpack does not like this for obvious reasons. Is there any type of module-based webpack config file that I can configure to ignore the node-based requires entirely so that this does not happen?
First option
As stated in the docs, in order to solve this isomorphic problem you could simply run two builds, one for each environment (node and web). The guide can be found here. Keep in mind you should probably mock any built ins in the clientConfig by adding this block
node: { fs: 'empty',//any other node lib used }. That way webpack will not complain and since your client code will be under the !IS_NODE condition the empty fs will never be used.
Although this is a solid solution you end up with 2 bundles and you need of course a way to distribute them to the correct platform each time.
Second way
This solution is based on the not very well known __non_webpack_require__ function. This is a webpack specific function that will instruct the parser to avoid bundling this module that is being requested and assume that a global require function is available. This is exactly what happens while running in node instead of a browser.
//webpack.config.js
{
mode: "development",
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
node: false
}
// nodeStuff.js
const fs = __non_webpack_require__('fs'); //this will be transformed to require('fs')
fs.writeFileSync('some','thing)
That way since nodeStuff.js will only be required under the IS_NODE condition, the native require will be available.
I would suggest to use __non_webpack_require__ on native libraries only, that you are sure that will be available!
I'm trying to create a minified version of a js library with webpack.
The library consists of one main function with prototypes that is exported and of several other functions it depends on that are imported in the file of the main function. This works without bundling and I assume that this file should the entry point for webpack.
I aim to bundle it into some mylib.min.js to be able access it in the browser like I would use jQuery or similar libraries. So I don't want to bundle the whole web app, just the JS library I wrote.
I'm not really getting along with it, since all tutorials show how to bundle the whole web app. My questions are:
how do I have to export the main function of the library to be able to access it in the browser?
how do I need to configure webpack?
how should I include and access the bundle in the browser?
If you could recommend any example (like tutorial, gitub repository that does this, ...) I would be happy! Any suggestions welcome!
Have you look at the documentation on the webpack website?
Here an example
For widespread use of the library, we would like it to be compatible in different environments, i.e. CommonJS, AMD, Node.js and as a global variable. To make your library available for consumption, add the library property inside output:
webpack.config.js
var path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
- filename: 'webpack-numbers.js'
+ filename: 'webpack-numbers.js',
+ library: 'webpackNumbers'
},
externals: {
lodash: {
commonjs: 'lodash',
commonjs2: 'lodash',
amd: 'lodash',
root: '_'
}
}
};
If you have any other question about that specific documentation just google webpack js authoring libraries. you'll be redirect to the good website. Website are subject to change pattern.
Since coming across RequireJS I have started to adopt it wholeheartedly as it seems a great way of organising dependencies etc.
For my current project I have created a 'package' of requireJS-organised modules, which will provide the needed database API, to many node.js applications.
But I have come across a stumbling block ... how can I allow third party applications to use my package, without needing to faff with requireJS?
My directory structure for my applications and API is currently as follows:
api_package/node_modules
api_package/controllers/*
api_package/views/*
api_package/helpers/*
api_package/models/*
api_package/main.js
application_1/node_modules
application_1/app.js
application_2/node_modules
application_2/app.js
I need my applications to be self-contained - so they can be easily deployed - so my current work around is to copy api_package/* into the 'node_modules' directory of application_1 & 2 and setting the their requirejs config to the following:
(function() {
var requirejs;
requirejs = require('requirejs').config({
baseUrl: __dirname,
nodeRequire: require,
packages: [
{
name: 'api_package',
location: './node_modules/api_package'
}
]
});
This feels a little dirty and wrong!
Is there a better way? Am I missing some packaging feature for requireJS?
Is it even possible to hide the implementation details of my api_package (the detail being that I am using requireJS) and allow applications to use it as they would any other module:
require('api_package')
You can use the amdefine package, which allows you to code to the AMD API and have the module work in node programs without requiring those other programs to use AMD.
In addition to the documentation on the amdefine github page, this is also documented on the RequireJS website.