Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<Emit("import($0)") can not be used> to instruct webpack to create async chunks #859

Closed
vasyl-purchel opened this issue Apr 29, 2017 · 1 comment

Comments

@vasyl-purchel
Copy link

Description

Webpack provides feature to create multiple bundle chunks and load them dynamically when needed (docs)

Through import('foo') can not be achieved with Emit currently because compiler will fail with:

Module build failed: SyntaxError: 'import' and 'export' may appear only with 'sourceType: module' (1:0)

Similar issue was reported for babylon: babylon/issues/220

And the solution is to add {sourceType: 'module'} to babel-template options:

// src/typescript/fable-utils/babel-plugins.js:75
var builtMacro = babelTemplate(macro, {sourceType: 'module', plugins: ["dynamicImport"]})(buildArgs);

note dynamicImport plugin is added there as it seems when babel-template is used here it ignores all bable plugins, and to support dynamic import I've copied what babel-plugin-syntax-dynamic-import is doing, without this compilation fails as '(' is not expected after 'import'

Repro code

// Foo.fs
module Foo
let answer = 22
// App.fs
module App

open Fable.Core
open Fable.Import
open Fable.PowerPack

[<Emit("import($0)")>]
let importMy (file:string) : JS.Promise<obj> = jsNative

promise {
    let! a = importMy "./Foo.fs"
    printfn ">>> %A" a
} |> Promise.start
// webpack.config.js
...
var babelOptions = {
  presets: [["es2017"]],
  plugins: ["transform-runtime", "syntax-dynamic-import"]
}
...

Existing workarounds

Atm it's possible to use System.import($0) which is deprecated in Webpack 2 or use require.ensure:

[<Emit("new Promise((res,rej)=>{require.ensure([],()=>{res({$0:require($1)})},err=>rej(err))})")>]
let importAsync (name:string) (file:string) : JS.Promise<obj> = jsNative

[<Emit("System.import($0)")>]
let systemImportAsync (file:string) : JS.Promise<obj> = jsNative

Related information

  • dotnet fable --version : 1.0.0-narumi-914
  • fable-core version: 1.0.0-narumi-914
  • Operating system: OS X El Capitan 10.11.6
@alfonsogarciacaro
Copy link
Member

It's probably better to deal with this in Fable.Core so I've added importDynamic (I also took the chance to add importSideEffects). According to my tests, it should work when bundling with JS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants