Typescript conditional import
up vote
1
down vote
favorite
I have an API with the following interface (just for the sake of example)
export type FrogAPI = {
getFrogs(): Promise<Frog>
putFrogs(frogs: Frog): Promise<void>
}
I have 2 versions of this, 1 mock version which reads and writes from localStorage:
export class LocalStorageFrogAPI implements FrogAPI {
getFrogs(): Promise<Frog> {
return Promise.resolve(JSON.parse(localStorage.getItem('@frogApi/frogs')))
}
// ...
}
And a real version which works with remote apis:
export class HttpFrogAPI implements FrogAPI {
getFrogs(): Promise<Frog> {
return fetch('/frogs').then((res) => res.json())
}
// ...
}
For development I'm using the localStorage one, for production the http one.
Question: How do I conditional import the right one, so at build time only the right sources are included in the output js? This is important because both files became quite bulky. I also don't want to expose the localStorage version at all in production for security reasons.
If I do this:
const ApiConstructor = process.env.ENV === 'development'
? require('./LocalStorageFrogAPI')
: require('./HttpFrogAPI')
export const API = new ApiConstructor() as FrogAPI
Both sources will still be included in the generated output. What's the right way of only having the right one in the output js? Is possible with some webpack config?
typescript webpack
add a comment |
up vote
1
down vote
favorite
I have an API with the following interface (just for the sake of example)
export type FrogAPI = {
getFrogs(): Promise<Frog>
putFrogs(frogs: Frog): Promise<void>
}
I have 2 versions of this, 1 mock version which reads and writes from localStorage:
export class LocalStorageFrogAPI implements FrogAPI {
getFrogs(): Promise<Frog> {
return Promise.resolve(JSON.parse(localStorage.getItem('@frogApi/frogs')))
}
// ...
}
And a real version which works with remote apis:
export class HttpFrogAPI implements FrogAPI {
getFrogs(): Promise<Frog> {
return fetch('/frogs').then((res) => res.json())
}
// ...
}
For development I'm using the localStorage one, for production the http one.
Question: How do I conditional import the right one, so at build time only the right sources are included in the output js? This is important because both files became quite bulky. I also don't want to expose the localStorage version at all in production for security reasons.
If I do this:
const ApiConstructor = process.env.ENV === 'development'
? require('./LocalStorageFrogAPI')
: require('./HttpFrogAPI')
export const API = new ApiConstructor() as FrogAPI
Both sources will still be included in the generated output. What's the right way of only having the right one in the output js? Is possible with some webpack config?
typescript webpack
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have an API with the following interface (just for the sake of example)
export type FrogAPI = {
getFrogs(): Promise<Frog>
putFrogs(frogs: Frog): Promise<void>
}
I have 2 versions of this, 1 mock version which reads and writes from localStorage:
export class LocalStorageFrogAPI implements FrogAPI {
getFrogs(): Promise<Frog> {
return Promise.resolve(JSON.parse(localStorage.getItem('@frogApi/frogs')))
}
// ...
}
And a real version which works with remote apis:
export class HttpFrogAPI implements FrogAPI {
getFrogs(): Promise<Frog> {
return fetch('/frogs').then((res) => res.json())
}
// ...
}
For development I'm using the localStorage one, for production the http one.
Question: How do I conditional import the right one, so at build time only the right sources are included in the output js? This is important because both files became quite bulky. I also don't want to expose the localStorage version at all in production for security reasons.
If I do this:
const ApiConstructor = process.env.ENV === 'development'
? require('./LocalStorageFrogAPI')
: require('./HttpFrogAPI')
export const API = new ApiConstructor() as FrogAPI
Both sources will still be included in the generated output. What's the right way of only having the right one in the output js? Is possible with some webpack config?
typescript webpack
I have an API with the following interface (just for the sake of example)
export type FrogAPI = {
getFrogs(): Promise<Frog>
putFrogs(frogs: Frog): Promise<void>
}
I have 2 versions of this, 1 mock version which reads and writes from localStorage:
export class LocalStorageFrogAPI implements FrogAPI {
getFrogs(): Promise<Frog> {
return Promise.resolve(JSON.parse(localStorage.getItem('@frogApi/frogs')))
}
// ...
}
And a real version which works with remote apis:
export class HttpFrogAPI implements FrogAPI {
getFrogs(): Promise<Frog> {
return fetch('/frogs').then((res) => res.json())
}
// ...
}
For development I'm using the localStorage one, for production the http one.
Question: How do I conditional import the right one, so at build time only the right sources are included in the output js? This is important because both files became quite bulky. I also don't want to expose the localStorage version at all in production for security reasons.
If I do this:
const ApiConstructor = process.env.ENV === 'development'
? require('./LocalStorageFrogAPI')
: require('./HttpFrogAPI')
export const API = new ApiConstructor() as FrogAPI
Both sources will still be included in the generated output. What's the right way of only having the right one in the output js? Is possible with some webpack config?
typescript webpack
typescript webpack
edited Nov 19 at 14:14
asked Nov 19 at 11:15
Balázs Édes
9,06223056
9,06223056
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
I had a similar requirement in the project I was working on.
There are 2 main options as I found. First - is to use async import like:
const ApiConstructor = await import("./LocalStorageFrogAPI");
This can be done conditionally. But there could be problems with race conditions here. Especially in the development. When all the imports will be loaded and cached except for this one. Could lead to errors.
The solution we ended up with is to create 2 versions of the file that uses that conditional import. So, in your case one file (for dev) would use
const ApiConstructor = require("./LocalStorageFrogAPI");
and for prod:
const ApiConstructor = require("./HttpFrogAPI");
The rest of the code will be the same.
And then you just substitute files using webpack depending on the build (dev/prod).
You could use NormalModuleReplacementPlugin for the substitution. Or otherwise, this article gives a good overview of how to separate dev and prod dependencies using webpack: Managing Dev and Production Builds with Webpack
Hey, thanks for the answer, can you show an example about substituting files? I don't quite understand how I would do that.
– Balázs Édes
Nov 19 at 14:12
@BalázsÉdes, I updated the answer.
– Daniil Andreyevich Baunov
Nov 19 at 15:41
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
I had a similar requirement in the project I was working on.
There are 2 main options as I found. First - is to use async import like:
const ApiConstructor = await import("./LocalStorageFrogAPI");
This can be done conditionally. But there could be problems with race conditions here. Especially in the development. When all the imports will be loaded and cached except for this one. Could lead to errors.
The solution we ended up with is to create 2 versions of the file that uses that conditional import. So, in your case one file (for dev) would use
const ApiConstructor = require("./LocalStorageFrogAPI");
and for prod:
const ApiConstructor = require("./HttpFrogAPI");
The rest of the code will be the same.
And then you just substitute files using webpack depending on the build (dev/prod).
You could use NormalModuleReplacementPlugin for the substitution. Or otherwise, this article gives a good overview of how to separate dev and prod dependencies using webpack: Managing Dev and Production Builds with Webpack
Hey, thanks for the answer, can you show an example about substituting files? I don't quite understand how I would do that.
– Balázs Édes
Nov 19 at 14:12
@BalázsÉdes, I updated the answer.
– Daniil Andreyevich Baunov
Nov 19 at 15:41
add a comment |
up vote
1
down vote
accepted
I had a similar requirement in the project I was working on.
There are 2 main options as I found. First - is to use async import like:
const ApiConstructor = await import("./LocalStorageFrogAPI");
This can be done conditionally. But there could be problems with race conditions here. Especially in the development. When all the imports will be loaded and cached except for this one. Could lead to errors.
The solution we ended up with is to create 2 versions of the file that uses that conditional import. So, in your case one file (for dev) would use
const ApiConstructor = require("./LocalStorageFrogAPI");
and for prod:
const ApiConstructor = require("./HttpFrogAPI");
The rest of the code will be the same.
And then you just substitute files using webpack depending on the build (dev/prod).
You could use NormalModuleReplacementPlugin for the substitution. Or otherwise, this article gives a good overview of how to separate dev and prod dependencies using webpack: Managing Dev and Production Builds with Webpack
Hey, thanks for the answer, can you show an example about substituting files? I don't quite understand how I would do that.
– Balázs Édes
Nov 19 at 14:12
@BalázsÉdes, I updated the answer.
– Daniil Andreyevich Baunov
Nov 19 at 15:41
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
I had a similar requirement in the project I was working on.
There are 2 main options as I found. First - is to use async import like:
const ApiConstructor = await import("./LocalStorageFrogAPI");
This can be done conditionally. But there could be problems with race conditions here. Especially in the development. When all the imports will be loaded and cached except for this one. Could lead to errors.
The solution we ended up with is to create 2 versions of the file that uses that conditional import. So, in your case one file (for dev) would use
const ApiConstructor = require("./LocalStorageFrogAPI");
and for prod:
const ApiConstructor = require("./HttpFrogAPI");
The rest of the code will be the same.
And then you just substitute files using webpack depending on the build (dev/prod).
You could use NormalModuleReplacementPlugin for the substitution. Or otherwise, this article gives a good overview of how to separate dev and prod dependencies using webpack: Managing Dev and Production Builds with Webpack
I had a similar requirement in the project I was working on.
There are 2 main options as I found. First - is to use async import like:
const ApiConstructor = await import("./LocalStorageFrogAPI");
This can be done conditionally. But there could be problems with race conditions here. Especially in the development. When all the imports will be loaded and cached except for this one. Could lead to errors.
The solution we ended up with is to create 2 versions of the file that uses that conditional import. So, in your case one file (for dev) would use
const ApiConstructor = require("./LocalStorageFrogAPI");
and for prod:
const ApiConstructor = require("./HttpFrogAPI");
The rest of the code will be the same.
And then you just substitute files using webpack depending on the build (dev/prod).
You could use NormalModuleReplacementPlugin for the substitution. Or otherwise, this article gives a good overview of how to separate dev and prod dependencies using webpack: Managing Dev and Production Builds with Webpack
edited Nov 19 at 15:41
answered Nov 19 at 11:25
Daniil Andreyevich Baunov
1,022526
1,022526
Hey, thanks for the answer, can you show an example about substituting files? I don't quite understand how I would do that.
– Balázs Édes
Nov 19 at 14:12
@BalázsÉdes, I updated the answer.
– Daniil Andreyevich Baunov
Nov 19 at 15:41
add a comment |
Hey, thanks for the answer, can you show an example about substituting files? I don't quite understand how I would do that.
– Balázs Édes
Nov 19 at 14:12
@BalázsÉdes, I updated the answer.
– Daniil Andreyevich Baunov
Nov 19 at 15:41
Hey, thanks for the answer, can you show an example about substituting files? I don't quite understand how I would do that.
– Balázs Édes
Nov 19 at 14:12
Hey, thanks for the answer, can you show an example about substituting files? I don't quite understand how I would do that.
– Balázs Édes
Nov 19 at 14:12
@BalázsÉdes, I updated the answer.
– Daniil Andreyevich Baunov
Nov 19 at 15:41
@BalázsÉdes, I updated the answer.
– Daniil Andreyevich Baunov
Nov 19 at 15:41
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53373443%2ftypescript-conditional-import%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown