Unable to acess kotlin js from javascript - javascript

I'm facing the issue where I'm not able to call any kotlin js function and getting 'something' is not defined.
I've tried compiling project with gradle but ended up following this tutorial and compiling with npm.
I attached my project here
EDIT: tested with maven and worked. However since maven is deprecated, I would like to use gradle or npm.
html code:
<body>
<script src="test.js"></script> //file generated in bin/bundle
<script>
(function() {
let a = new test.Test(); //test - module, Test - my class, error occurrs at this line
a.test(); //test - method in class Test
})()
</script>
</body>
however it always results in
Uncaught ReferenceError: test is not defined
package.json:
{
"name": "test",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"build": "shx rm -rf bin && webpack && shx rm -rf bin/build/kotlin-test*",
"test": "mocha bin/test"
},
"author": "",
"license": "ISC",
"dependencies": {
"kotlin": "^1.3.70"
},
"devDependencies": {
"#jetbrains/kotlin-webpack-plugin": "^3.0.2",
"kotlin-test": "^1.3.70",
"mocha": "^7.1.0",
"shx": "^0.3.2",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11"
},
"description": ""
}
webpack.config.js:
const KotlinWebpackPlugin = require('#jetbrains/kotlin-webpack-plugin');
module.exports = {
entry: 'test', // This tells webpack where to begin for bundling
resolve: {
modules: ['bin/build', 'node_modules'], // Webpack will use this to look for anything that is required
},
output: {
path: __dirname + '/bin/bundle', // This is where the bundle will go
filename: 'test.js', // The bundle will be called vectron.js
},
plugins: [
//Step one - Create a test build
new KotlinWebpackPlugin({
src: __dirname, // Build Everything
output: 'bin/test', // Output to bin/test
moduleName: 'test', // Will create vectron.js
moduleKind: 'commonjs', // Create commonjs modules
librariesAutoLookup: true, // Uses node_modules for libraries
packagesContents: [require('./package.json')], // Points to package.json for dependencies
}),
// Step two - Create a production build
new KotlinWebpackPlugin({
src: __dirname + '/src', // Build only what is in src
output: 'bin/build', // Output to bin/build
moduleName: 'test', // Create a file called vectron.js
moduleKind: 'commonjs', // Create commonjs modules
metaInfo: true, // Include .meta.js files
sourceMaps: true, // Include Source mappings
librariesAutoLookup: true, // Uses node_modules for libraries
packagesContents: [require('./package.json')], // Points to package.json for dependencies
}),
],
};
my class:
class Test {
fun test() {
println("test")
}
}
EDIT: npm compilation of test.js:
(function (_, Kotlin) {
'use strict';
var println = Kotlin.kotlin.io.println_s8jyv4$;
var Kind_CLASS = Kotlin.Kind.CLASS;
function Test() {
}
Test.prototype.test = function () {
println('test');
};
Test.$metadata$ = {
kind: Kind_CLASS,
simpleName: 'Test',
interfaces: []
};
_.Test = Test;
Kotlin.defineModule('test', _);
return _;
}(module.exports, require('kotlin'))); //error: module is not defined
//# sourceMappingURL=test.js.map
maven kotlin plugin output of test.js:
if (typeof kotlin === 'undefined') {
throw new Error("Error loading module 'test'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'test'.");
}var test = function (_, Kotlin) {
'use strict';
var println = Kotlin.kotlin.io.println_s8jyv4$;
var Kind_CLASS = Kotlin.Kind.CLASS;
function Test() {
}
Test.prototype.test = function () {
println('test');
};
Test.$metadata$ = {
kind: Kind_CLASS,
simpleName: 'Test',
interfaces: []
};
_.Test = Test;
Kotlin.defineModule('test', _);
return _;
}(typeof test === 'undefined' ? {} : test, kotlin);

moduleKind was wrong in the build.gradle. Setting it to 'plain' fixed the issue.
Thank you

Related

how add coffeescript in svelte on Rails 7?

I have a Rails 7 app with esbuild :
esbuild.config.js :
#!/usr/bin/env node
const watch = process.argv.includes("--watch");
const esbuild = require('esbuild')
const coffeeScriptPlugin = require('esbuild-coffeescript');
const esbuildSvelte = require('esbuild-svelte');
const sveltePreprocess = require('svelte-preprocess');
esbuild
.build({
entryPoints: ["app/javascript/all.js"],
bundle: true,
outfile: "app/assets/builds/all.js",
// outdir: "app/assets/builds/",
plugins: [
esbuildSvelte({
preprocess: sveltePreprocess({coffeescript: { bare: true }}),
}),
// coffeeScriptPlugin({bare: true}), I TRIED THIS TOO...
],
logLevel: "debug",
watch: watch
})
.catch(() => process.exit(1));
my.svelte :
<script lang="coffee">
test = ->
console.log 'test coffee'
test()
</script>
got an error :
$ yarn build --watch yarn run v1.22.19 $ node ./esbuild.config.js
--watch ✘ [ERROR] [plugin esbuild-svelte] Unexpected token
app/javascript/all.js:3:3:
3 │ 1:
╵ ^
2: <script lang="coffee">
3: test = ->
^
4: console.log 'test coffee'
5: test()
The plugin "esbuild-svelte" was triggered by this import
app/javascript/svelte_src.js:6:32:
6 │ import DemoSvelteComponent from './svelte/DemoSvelteComponent.svelte'
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error [watch] build finished, watching for changes... error Command
failed with exit code 1. info Visit
https://yarnpkg.com/en/docs/cli/run for documentation about this
command.
$ node -v
v18.4.0
package.json :
{
"name": "app",
"private": "true",
"dependencies": {
"#hotwired/stimulus": "^3.0.1",
"#hotwired/turbo-rails": "^7.1.3",
"esbuild": "^0.14.43",
"esbuild-coffeescript": "^2.1.0",
"esbuild-svelte": "^0.7.1",
"sass": "^1.52.3",
"svelte": "^3.48.0",
"svelte-preprocess": "^4.10.7"
},
"scripts": {
"build": "node ./esbuild.config.js"
}
}
How add coffeescript in svelte with Rails ?
This setup works with node v18.4.0 v16.15.1 v14.19.3. It turned out pretty much identical to what you have, except I don't know what's in your all.js file.
// package.json
{
"name": "app",
"private": "true",
"dependencies": {
"#hotwired/stimulus": "^3.0.1",
"#hotwired/turbo-rails": "^7.1.3",
"esbuild": "^0.14.43",
"esbuild-coffeescript": "^2.0.0",
"esbuild-svelte": "^0.7.1",
"svelte": "^3.48.0",
"svelte-preprocess": "^4.10.7"
},
"scripts": {
"build": "node ./esbuild.config.js"
}
}
// esbuild.config.js
const watch = process.argv.includes("--watch");
const esbuild = require("esbuild");
const esbuildSvelte = require("esbuild-svelte");
const sveltePreprocess = require("svelte-preprocess");
esbuild
.build({
entryPoints: ["app/javascript/all.js"],
outdir: "app/assets/builds/",
bundle: true,
sourcemap: true,
plugins: [
esbuildSvelte({
preprocess: sveltePreprocess(),
}),
],
logLevel: "debug",
watch: watch,
})
.catch(() => process.exit(1));
// app/javascript/all.js
import App from "./my.svelte";
new App({ target: document.body });
<!-- app/javascript/my.svelte -->
<script lang="coffee">
test = ->
console.log 'test coffee'
test()
</script>
Compiles:
$ yarn build --watch
yarn run v1.22.19
$ node ./esbuild.config.js --watch
[watch] build finished, watching for changes...
[watch] build started (change: "app/javascript/my.svelte")
[watch] build finished
and shows up in the browser console:
test coffee my.svelte:1
This is a smaller working example, maybe it'll help eliminate the source of the error. It compiles my.svelte file directly and prints out the source.
// package.json
{
"dependencies": {
"esbuild": "^0.14.43",
"esbuild-coffeescript": "^2.1.0",
"esbuild-svelte": "^0.7.1",
"svelte": "^3.48.0",
"svelte-preprocess": "^4.10.7"
}
}
// esbuild.config.js
require("esbuild").build({
entryPoints: ["app/javascript/my.svelte"],
plugins: [require("esbuild-svelte")({ preprocess: require("svelte-preprocess")() })],
}).catch(() => process.exit(1));
$ node --version
v18.4.0
$ node ./esbuild.config.js
import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
function instance($$self) {
var test;
test = function() {
return console.log("test coffee");
};
test();
return [];
}
class My extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, null, safe_not_equal, {});
}
}
export default My;
I don't find the problem, I make new app and copy files, I don't see when exactly that works, but that works ... ^^
May be a bad invisible character was in file?
So It's works fine with include esbuild-coffeescript ...
That stay a mystery for my use case (I try checkout from git and bug don't come back.... realy strange)
I've met the same problem in my rails app and my solution was using another build script
old:
"build-es": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets"
new:
"build": "node ./esbuild.config.js",

"Failed to resolve module specifier" or "window is not defined" when I import WASM in JS worker

I am trying to import my WASM library (written in Rust) inside a JS worker. And I get the error:
Uncaught (in promise) TypeError: Failed to resolve module specifier 'mylib'
Or if I try to use worker-loader the error is different, but in the same line:
window is not defined
What is the nature of the errors and how am I supposed to fix it?
The details are represented below. I tried to make the example as minimal as possible (without worker-loader).
The structure of my project is:
wasm-worker-example/
mylib/
pkg/*
src/
lib.rs
Cargo.toml
www/
bundles/*
node_modules/*
index.html
index.js
my.worker.js
package.js
webpack.config.js
lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn concat(a: &str, b: &str) -> String {
a.to_string() + b
}
Cargo.toml
[package]
name = "mylib"
version = "0.1.0"
authors = ["Alexander <mail#fomalhaut.su>"]
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
package.json
{
"name": "www",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"mylib": "file:../mylib/pkg",
"#babel/core": "^7.9.6",
"babel-loader": "^8.1.0",
"webpack": "^4.43.0",
"webpack-bundle-tracker": "^1.0.0-alpha.1",
"webpack-cli": "^3.3.11"
}
}
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const BundleTracker = require('webpack-bundle-tracker');
module.exports = {
mode: 'development',
context: __dirname,
entry: './index',
output: {
path: path.resolve('./bundles/'),
filename: 'app.js',
publicPath: "/bundles/"
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
],
},
};
index.html
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="bundles/app.js"></script>
</head>
<body>
</body>
</html>
index.js
import("mylib").then(wasm => {
// It works fine
console.log(wasm.concat("qwe", "rty"));
var worker = new Worker("my.worker.js");
worker.postMessage('Message to worker');
});
my.worker.js
// Error: Uncaught (in promise) TypeError: Failed to resolve module specifier 'mylib'
import("mylib").then(wasm => {
// Not reached
console.log(wasm.concat("qwe", "rty"));
self.addEventListener('message', e => {
console.log(e.data);
});
});
I prepare mylib with (in mylib):
wasm-pack build
For frontend (in www):
npm install
./node_modules/.bin/webpack
To run (in www):
http-server

Gulp and browserify give error: Cannot find module 'jquery' from 'C:....'

The error I receive is:
Error: Cannot find module 'jquery' from 'F:...\newstyle\assets\lib\helper\html\img\js'
at
C:\Users...\AppData\Roaming\npm\node_modules\browserify\node_modules\browser-resolve\node_modules\resolve\lib\async.js:46:17
at process (C:\Users...\AppData\Roaming\npm\node_modules\browserify\node_modules\browser-resolve\node_modules\resolve\lib\async.js:173:43)
at ondir (C:\Users...\AppData\Roaming\npm\node_modules\browserify\node_modules\browser-resolve\node_modules\resolve\lib\async.js:188:17)
at load (C:\Users...\AppData\Roaming\npm\node_modules\browserify\node_modules\browser-resolve\node_modules\resolve\lib\async.js:69:43)
at onex (C:\Users...\AppData\Roaming\npm\node_modules\browserify\node_modules\browser-resolve\node_modules\resolve\lib\async.js:92:31)
at C:\Users...\AppData\Roaming\npm\node_modules\browserify\node_modules\browser-resolve\node_modules\resolve\lib\async.js:22:47
at FSReqWrap.oncomplete (fs.js:153:21)
My directory structure is as follows:
newstyle/assets/npm/index.js
newstyle/assets/npm/package.json
newstyle/assets/npm/gulpfile.js
newstyle/assets/lib/helper/html/img/js/img.module.js
My package.json looks like this:
{
"name": "newstyle",
"version": "1.0.0",
"description": "styles and libraries",
"main": "index.js",
"dependencies": {
"#tschallacka/assetmanager": "^1.0.0",
"#tschallacka/jquery.oc.foundation": "^1.0.2",
"#tschallacka/jquery.render": "^1.0.0",
"#tschallacka/jquery.request": "^1.0.0",
"#tschallacka/oc.foundation.base": "^1.0.1",
"#tschallacka/oc.foundation.controlutils": "^1.0.1",
"#tschallacka/oc.foundation.request": "^1.0.0",
"animate.css": "^3.7.0",
"bootstrap-less": "^3.3.8",
"flexslider": "^2.7.2",
"font-awesome": "^4.7.0",
"jquery": "^3.4.1",
"jquery-touchswipe": "^1.6.19",
"jquery.easing": "^1.4.1",
"lazysizes": "^4.1.8",
"liquidslider": "git+https://git#github.com/KevinBatdorf/liquidslider.git",
"popper.js": "^1.15.0",
"sweetalert2": "^8.11.1"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
My index.js like this:
require('#tschallacka/oc.foundation.base');
require('#tschallacka/oc.foundation.controlutils');
// ====================== TROUBLE CAUSING LINE!! ==========================
require('../assets/lib/helper/html/img/js/img.module.js');
the code in newstyle/assets/lib/helper/html/img/js/img.module.js
var $ = require('jquery');
var Base = require('#tschallacka/oc.foundation.base');
var controlUtils = require('#tschallacka/oc.foundation.controlutils');
My gulpfile.js
'use strict';
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var log = require('gulplog');
var less = require('gulp-less');
var cssmin = require('gulp-cssmin');
var rename = require('gulp-rename');
gulp.task('javascript', function () {
// set up the browserify instance on a task basis
var b = browserify({
entries: './index.js', // Source name
debug: true
});
return b.bundle()
.pipe(source('closure.js'))// Resulting filename
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
// Add transformation tasks to the pipeline here.
.pipe(uglify())
.on('error', log.error)
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('../js/'));
});
gulp.task('watch', function () {
gulp.watch('./*.less', ['less']);
});
gulp.task('less', function () {
return gulp.src('./style.less')
.pipe(less({
relativeUrls: true
}).on('error', function (err) {
console.log(err);
}))
.pipe(cssmin().on('error', function(err) {
console.log(err);
}))
.pipe(rename('closure.css'))
.pipe(gulp.dest('../css/'));
});
When I run this without the trouble causing line, everything works fine, it finds the modules and it compiles without a hitch. No problems with not finding the modules.
But when I require that script, the module I required as test from the "parent" script suddenly cannot be found anymore, even though it should still be in the cache by string name.
It does work if I 'require' the files by filename, but that's less than desirable because then I constantly need to check directory nesting.
What causes this and how can I resolve this?
Things I've tried:
setting basedir
var b = browserify({
entries: './index.js', // Source name
debug: true,
basedir: __dirname
});
npm update from 6.4.1 to 6.9.0
Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
npm install -g npm-windows-upgrade
npm-windows-upgrade
updated gulp:
+ gulp#4.0.2
updated 6 packages in 19.938s
The solution is rather simple, but not easy to get to the conclusion what causes the error, you have to add node_modules to the 'paths' variable of browserify in your gulpfile.js
// set up the browserify instance on a task basis
var b = browserify({
entries: './index.js', // Source name
debug: true,
paths: ['./node_modules'] // <--- this line here
});

Transpiled ES5 not recognized by Firebase Cloud Functions: firebase is undefined

A bit of an introduction, currently (at the time I wrote this) Firebase functions does not support features like async and await from a more recent version of node. I am trying to overcome this by transpiling my code to the node version they currently support.
I am using webpack 3 to bundle my react.js web application. I have set up two separate configurations -one for development and the other production. I use a third confirguration to execute as a second task on production pipiline to take cloudfunctions.js and spit it out to the deployment dir functions/index.js using babel to transpile the code,
Instead of describing the transpile requirements in a .babelrc, I am adding those details using webpack to the options configuration object in inside the module in rules.
I've been successful transpiling the code, yet Firebase keeps complaining about 'firebase' not being defined. I've narrowed down the trigger of this error to the very first line of code which is an import.
Any suggestion that can point me to the right direction is truly appreciated.
import functions from ''firebase-functions';
As a matter of fact, I've tried Commonjs (using require) and made other attempts at ES6 import/exports.
Package.json:
{
"scripts": {
"start":"node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack/dev.config.js",
"build": "cross-env NODE_ENV=production node ./node_modules/webpack/bin/webpack.js --config webpack/prod.config.js"
},
"dependencies": {
"#babel/polyfill": "^7.0.0-beta.40",
"firebase-admin": "^5.5.1",
"firebase-functions": "^0.7.3",
},
"devDependencies": {
"#babel/cli": "^7.0.0-beta.40",
"#babel/core": "^7.0.0-beta.40",
"#babel/plugin-proposal-object-rest-spread": "^7.0.0-beta.40",
"#babel/preset-env": "^7.0.0-beta.40",
"babel-loader": "^8.0.0-beta.0",
"babel-preset-react": "^6.24.1",
"cross-env": "^5.1.3",
"generate-json-webpack-plugin": "^0.2.2",
"uglifyjs-webpack-plugin": "^1.1.8",
"webpack": "^3.10.0",
"webpack-merge": "^4.1.1"
}
}
functions.config.js (webpack)
const
path = require('path'),
pkg = require('../package'),
GenerateJsonPlugin = require('generate-json-webpack-plugin'),
UglifyJSPlugin = require('uglifyjs-webpack-plugin'),
webpack = require('webpack');
const externals = [
'firebase-admin',
'firebase-functions'
]
const genPackage = () => ({
name : 'functions',
private : true,
main : 'index.js',
license : 'MIT',
dependencies : externals.reduce( (acc, name) => Object.assign({}, acc, { [name]: pkg.dependencies[name] || pkg.devDependencies[name] }), {} )
})
module.exports = {
entry : [
'#babel/polyfill',
path.join(__dirname, '../cloudfunctions.js')
],
output : {
path : path.join(__dirname, '../functions/'),
filename : 'index.js'
},
module : {
rules: [
{
test : /\.js$/,
loader : 'babel-loader',
options :
{
presets : [
[
'#babel/env',
{
option : {
targets : {
node : '6.11.5'
}
}
}
]
],
plugins: [
'#babel/plugin-proposal-object-rest-spread'
]
}
,
exclude : /node_modules/
}
]
},
externals : externals.reduce( (acc, name) => Object.assign({}, acc, { [name]: true }), {} ),
plugins : [
new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) }),
new UglifyJSPlugin(),
new GenerateJsonPlugin('package.json', genPackage())
]
}
Environtment
OS: Windows 10
Node Version: 8.9.4
Pkg Manager: npm
Shell: Windows Shell
Browser & version: Chrome 64.0.3282.186
Language: Javascript
Expected Behaviour
Transpile succesfully.
Deploy to firebase successfully
Actual Behaviour
Transpiles succesfully.
Continue receiving this log with the same error after hitting the firebase deploy --only functions command:
i deploying functions
i functions: ensuring necessary APIs are enabled...
+ functions: all necessary APIs are enabled
i functions: preparing functions directory for uploading...
Error: Error occurred while parsing your function triggers.
ReferenceError: firebase is not defined
at Object.module.exports (C:\Users\Andrew Redican\Compass\functions\index.js:9040:18)
at __webpack_require__ (C:\Users\Andrew Redican\Compass\functions\index.js:20:30)
at Object.module.exports (C:\Users\Andrew Redican\Compass\functions\index.js:8967:17)
at __webpack_require__ (C:\Users\Andrew Redican\Compass\functions\index.js:20:30)
at Object.<anonymous> (C:\Users\Andrew Redican\Compass\functions\index.js:3687:18)
at __webpack_require__ (C:\Users\Andrew Redican\Compass\functions\index.js:20:30)
at C:\Users\Andrew Redican\Compass\functions\index.js:63:18
at Object.<anonymous> (C:\Users\Andrew Redican\Compass\functions\index.js:66:10)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)
cloundFunctions.js [input]
let functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
functions/index.js [output]
Depending on whether I include Uglify plugin or not the output will be minified or normal.
Webpack also takes in #babel/polyfill so help functions are added to this file.
I have not included outfile since unmifinify version is 9049 lines of code long, while minified is not legibile.
I've Tried
Used Babel 6 and then Babel 7 still unfruitful.
Environment Configuartion https://firebase.google.com/docs/functions/config-en
I've tried providing the access object directly hardcoded.
I am obviosly missing something, but I've went over this article/repo several times now.
Other Notes
I am trying to get away from typescript and dealing promises' callback hell as far as I can. I am also trying not to rely directly on npm to run command directly but rather take advantage of webpack.
I was able have webpack use babel to transpile code to functions/index.js. I figured out the problem.
When using webpack, make sure you specify output.libraryTarget to 'umd'.
Below is the webpack confg file:
const
path = require('path'),
pkg = require('../package'),
GenerateJsonPlugin = require('generate-json-webpack-plugin');
const
externals = [
'firebase-admin',
'firebase-functions'
],
genPackage = () => ({
name : 'functions',
private : true,
dependencies: externals.reduce(
(acc, name) =>
Object.assign({}, acc, {
[name]:
pkg.dependencies[name] ||
pkg.devDependencies[name]
}),
{}
)
});
module.exports = {
entry : [
'babel-polyfill',
'./cloudfunctions.js'
],
output: {
path : path.resolve(__dirname,'../functions'),
filename : 'index.js',
libraryTarget : 'umd'
},
module : {
rules : [
{
exclude : /node_modules/,
loader : 'babel-loader',
query : {
presets : [ 'babel-preset-env' ]
}
}
]
},
resolve: {
extensions: ['.js']
},
node: {
fs : 'empty',
net : 'empty',
tls : 'empty'
},
externals: externals.reduce(
(acc, name) => Object.assign({}, acc, { [name]: true }),{}
),
plugins: [
new GenerateJsonPlugin('package.json', genPackage())
]
};
Cheers!

How to add a compile-time global variable in webpack?

I've got a dynamically configurable webpack setup, with some custom loaders. Each of these loaders needs a configuration object which is only known dynamically, at compile time, so it's not possible to hard code it in loader's options. How can loaders access this object? Is there a "canonical" way to have a compile-time global in webpack?
Basically, my setup allows for multiple dynamic build-time configurations, it looks like this:
// webpack.config.js
let defaults = {
....
module: {
loaders: [
{
test: '.some.special.stuff',
loader: 'my-own-loader',
}
}
module.exports = function main() {
let BUILD_CONFIG = require(process.env.BUILD_CONFIG);
....
return defaults;
}
So webpack is supposed to be called like BUILD_CONFIG=some-config.js webpack. Note that some-config.js contains a lot of non-webpack stuff, so I can't just return it from main or merge it with defaults
Now, I have my-own-loader in my-own-loader.js:
// my-own-loader.js
module.exports = function main(content) {
...
My question is how to access that BUILD_CONFIG variable from webpack's main in the loader's main.
I think I understand what you are trying to do and have an example project detailing the process.
To start, I'm going to set an environment variable named TEST_VAR through whatever mechanism my platform supports. I'm on macOS, so that's export TEST_VAR=fizzbuzz. My loader.js is able to use that environment variable through the node convention: process.env.TEST_VAR.
Remember, your webpack.config.js is still a node run JavaScript file. You can use all the built-ins that node supports including process.env.
Consider the following files and structure:
Structure
webpack-test
|- package.json
|- webpack.config.js
|- index.html
|- /dist
|- bundle.js
|- /loaders
| obj-loader.js
|- /res
|- /obj
|- dummy.obj
|- /src
|- index.js
package.json
{
"name": "webpack-test",
"version": "0.0.1",
"main": "index.js",
"dependencies": {
"webpack": "^3.8.1"
},
"devDependencies": {
"http-server": "^0.10.0",
"loader-utils": "^1.1.0",
},
"scripts": {
"start": "http-server .",
"build": "webpack",
},
}
webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
resolveLoader: {
modules: [
path.resolve(__dirname, "loaders")
]
},
module: {
rules: [
{
test: /\.obj$/,
use: {
loader: "obj-loader",
options: {
dummyText: "lorem ipsum"
}
}
}
]
}
};
/loaders/obj-loader.js
const loaderUtils = require("loader-utils"),
schemaUtils = require("schema-utils");
function loader(source) {
const options = loaderUtils.getOptions(this);
console.log(options);
let tmp = process.env.TEST_VAR;
if (tmp === undefined) {
console.warn("TEST_VAR is not defined");
}
return `export default function(){return "TEST_VAR: ${tmp} || ${source} || ${options.dummyText}";}`;
}
module.exports = loader;
/res/obj/dummy.obj
Hello
/src/index.js
import dummy from "../res/obj/dummy.obj";
(function () {
"use strict";
function main() {
document.querySelector("p").innerHTML = dummy();
}
document.addEventListener("DOMContentLoaded", main);
}());
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Webpack Test</title>
<script src="dist/bundle.js"></script>
</head>
<bod>
<main>
<h1>Webpack Test</h1>
<p>Lorem Ipsum</p>
</main>
</bod>
</html>
Whenever I build and run this webpage, I get what amounts to:
<main>
<h1>Webpack Test</h1>
<p>TEST_VAR: fizzbuzz || Hello || lorem ipsum</p>
</main>
Where "fizzbuzz" was added from the environment variable, "Hello" the source is from /res/obj/dummy.obj, and "lorem ipsum" is the text that I specified as the dummyText option for the obj-loader. However, it could have just as easily come from an environment variable that I set.
Additional update based on edit
Considering your edit, what about this; instead of setting the rule in defaults set it in the exported function to get scope access. Then add your loader rules based on the new rule syntax: module.loaders is now module.rules. That way you have access to options in your custom loader and thus have access to BUILD_CONFIG.
Newer webpack.config.js
// Hypothetically you run:
// export BUILD_CONFIG=some-config.js
// Which sets:
// process.env.BUILD_CONFIG = "some-config.js";
// New Webpack loader/rules syntax
// https://webpack.js.org/guides/migrating/#module-loaders-is-now-module-rules
let defaults = {
module: {
rules: [
/*
*Set this later in exported function
{
test: ".some.special.stuff",
use: {
loader: "my-own-loader",
options: {
some: "options"
}
}
}
*/
]
}
};
module.exports = function (content) {
let BUILD_CONFIG = require(process.env.BUILD_CONFIG);
// Other code
let dd = defaults;
defaults.module.rules.push({
test: ".some.special.stuff",
use: {
loader: "my-own-loader",
options: {
stuffFromEnvConfig: BUILD_CONFIG
}
}
});
return dd;
};
my-own-loader.js
const loaderUtils = require("loader-utils"),
schemaUtils = require("schema-utils");
module.exports = function main(content) {
const options = loaderUtils.getOptions(this);
console.log(options);
let tmp;
if (options.stuffFromEnvConfig.useFirst) {
tmp = "Fizz";
} else {
tmp = "Buzz";
}
return `export default function(){return "TEST_VAR: ${tmp}";}`;
};

Categories

Resources