How import variables or functions declared in different javascript files for WebExtension? - firefox-addon-webextensions

This issue appears in Firefox Developer Edition 53.0a2.
This take place in context of WebExtension development.
I have a lib script that export a simple variable.
my-lib.js
export const foo = 42
my-background-script.js
import foo from 'my-lib'
// ...
This throws a SyntaxError: import declarations may only appear at top level of a module
How can I import variables or functions declared in different javascript files ?

ES6 modules support is not far enough yet (source MDN)
The use of Webpack or Babel is the option to transpile the code to a compatible javascript version.

Related

Can I use a compiled ReasonReact component together with the CDN version of React? [duplicate]

Building a component with Reason and React always gives me an module import statement for "react", which cannot be found if React is included from a CDN. Is there a solution for this? I've tried to define window.react = React in index.html without success. es6-global setting does not change anything.
I'm not using a bundling program like webpack.
Edit: Possibly relevant thread from Reason forum: https://reasonml.chat/t/can-one-load-reasonml-es6-modules-without-a-bundler/2219
Similar issue (not resolved): can one load reasonml es6 modules without a bundler
importmap (not yet implemented in browsers) could be another solution for this: Using ES6 Modules without a Transpiler/Bundler step
Technically, yes you can, but it's not going to be as easy as going with the npm flow and using a bundler.
The ReasonReact bindings are written in a way that produces output JavaScript that imports modules like:
import * as React from "react";
(If using ES6 module style.)
If using a CDN you would probably want an output that looks like this:
import * as React from "https://some.cdn/react";
The syntax (from the ReasonReact repo) that controls the output JS is:
[#bs.module "react"]
external createElement: (component('props), 'props) => element = "createElement";
If you changed it to:
[#bs.module "https://some.cdn/react"]
external createElement: (component('props), 'props) => element = "createElement";
...then you'd get the desired output. But the problem is then you need to change the sources ... i.e. maintain or find forked bindings for React for that CDN. Or set up some code automation that does a find-and-replace of [#bs.module "react"] with [#bs.module "https://some.cnd/react"]. So either way, it's not as simple as using a bundler.

Can I make Reason+React import react module from CDN?

Building a component with Reason and React always gives me an module import statement for "react", which cannot be found if React is included from a CDN. Is there a solution for this? I've tried to define window.react = React in index.html without success. es6-global setting does not change anything.
I'm not using a bundling program like webpack.
Edit: Possibly relevant thread from Reason forum: https://reasonml.chat/t/can-one-load-reasonml-es6-modules-without-a-bundler/2219
Similar issue (not resolved): can one load reasonml es6 modules without a bundler
importmap (not yet implemented in browsers) could be another solution for this: Using ES6 Modules without a Transpiler/Bundler step
Technically, yes you can, but it's not going to be as easy as going with the npm flow and using a bundler.
The ReasonReact bindings are written in a way that produces output JavaScript that imports modules like:
import * as React from "react";
(If using ES6 module style.)
If using a CDN you would probably want an output that looks like this:
import * as React from "https://some.cdn/react";
The syntax (from the ReasonReact repo) that controls the output JS is:
[#bs.module "react"]
external createElement: (component('props), 'props) => element = "createElement";
If you changed it to:
[#bs.module "https://some.cdn/react"]
external createElement: (component('props), 'props) => element = "createElement";
...then you'd get the desired output. But the problem is then you need to change the sources ... i.e. maintain or find forked bindings for React for that CDN. Or set up some code automation that does a find-and-replace of [#bs.module "react"] with [#bs.module "https://some.cnd/react"]. So either way, it's not as simple as using a bundler.

import/export according to environment variable

For a clientSide app I would like to select a specific import according to the environment variables that were setup in the package.json.
eg:`
if (process.env.IS_DEV)
import { store } from '../../../index.js
else
import { store } from './index.js';
`
Is there anyway to do this.
I currently receive the error -
Parsing error: 'import' and 'export' may only appear at the top level
As the error says, import can be only at top level.
If you are using some bundler such as webpack or parcel, you can use a require instead.
Pay attention: that both of the implementations will be inside the bundle, and only one of them will be executed.
You can use web pack dynamic import to enable this if you are using web pack 1
$ npm install babel-plugin-dynamic-import-webpack --save-dev
then in .babelrc
{
"plugins": ["dynamic-import-webpack"]
}
https://github.com/airbnb/babel-plugin-dynamic-import-webpack
in the newer versions of web pack, you can do this without Babel
https://webpack.js.org/api/module-methods/#dynamic-expressions-in-import
the other solution which mentioned before is using require
but i think here you can do it in a different way to avoid having this files in the bundled result you can add build script to run before building the dist which replace this import inside the file completely before bundle it to frontend app
Maybe is better to check process.env.IS_DEV inside the store file and export different values based on the current env

Converting to TypeScript files for AngularJS app

I have a large AngularJS app which I am in the process of upgrading (with NgUpgrade, webpack etc.) To start with, my new Angular (4) components are .ts files but my old AngularJS parts are .js files, transpiled using the Babel loader for webpack.
I would like to migrate all .js files to .ts files so that I can have everything go through the TypeScript compiler and no longer require Babel etc.
For the most part, the app runs fine (with a few small tweaks) by just renaming the files from .js to .ts and adding an import for angular at the top:
import * as angular from 'angular';
However, when I run my app, I now see a warning:
WARNING: Tried to load angular more than once.
This makes sense because Angular would be loaded once by the global script include, and once by the module import.
I can't avoid having the global script include, because I am using other scripts that require the angular global variable to be present.
As such, I think I should be using the global variable, but need to declare it to keep the TypeScript compiler happy (as per NgUpgrade documentation). I have tried changing the top of each file to:
declare var angular: angular.IAngularStatic;
This doesn't work and I get an error like the following:
TS2503: Cannot find namespace 'angular'.
Can anyone please tell me what is going wrong? I have installed #types/angular with npm/yarn and do not have typeRoots or types in my tsconfig.json file. My understanding is that this should automatically find the declarations in node_modules/#types but this doesn't seem to be the case?
I've found a solution which is working nicely (thanks to https://stackoverflow.com/a/42035067/1145963).
Added a .d.ts file at the root of my project:
declare global {
const angular: ng.IAngularStatic;
}
export {};
This allows me to use the angular global from anywhere, without needing any import or declare statements at the top of the files and without needing to do any special Webpack configuration.

How React Native resolves ProgressBarAndroid?

Unlike other components of React Native, ProgressBarAndroid isn't exported from react-native module, rather you need to include it as a separate module like this
var ProgressBar = require('ProgressBarAndroid');
It is very much clear from the source code that the files are loaded from here
https://github.com/facebook/react-native/tree/v0.25.1/Libraries/Components/ProgressBarAndroid
It works well when imported in the project but the same require() statement fails to find the module inside another third party library which I am writing.
Where could be the resolution definition for this file? Is it something to do with Babel's React Native preset? The same require() statement doesn't find the module with Node CLI tool.

Resources