feat: add DotEnv support

This commit is contained in:
Igor Randjelovic
2021-03-02 18:49:15 +01:00
parent 0fc94434b2
commit 3c44a553c3
6 changed files with 614 additions and 2 deletions

View File

@ -0,0 +1,510 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`base configuration for android 1`] = `
"{
mode: 'development',
externals: [
'package.json',
'~/package.json'
],
devtool: 'inline-source-map',
target: 'node',
output: {
path: '__jest__/platforms/android/app/src/main/assets/app',
pathinfo: false,
publicPath: '',
libraryTarget: 'commonjs',
globalObject: 'global'
},
resolve: {
symlinks: true,
alias: {
'~': '__jest__/src',
'@': '__jest__/src'
},
extensions: [
'.android.ts',
'.ts',
'.android.js',
'.js',
'.android.css',
'.css',
'.android.scss',
'.scss',
'.android.json',
'.json'
]
},
resolveLoader: {
modules: [
'node_modules/@nativescript/webpack/dist/loaders',
'node_modules'
]
},
module: {
rules: [
/* config.module.rule('ts') */
{
test: [
/\\\\.ts$/
],
use: [
/* config.module.rule('ts').use('ts-loader') */
{
loader: 'ts-loader',
options: {
transpileOnly: true,
allowTsInNodeModules: true,
compilerOptions: {
sourceMap: true,
declaration: false
},
getCustomTransformers: function () { /* omitted long function */ }
}
}
]
},
/* config.module.rule('js') */
{
test: /\\\\.js$/,
exclude: [
/node_modules/
],
use: [
/* config.module.rule('js').use('babel-loader') */
{
loader: 'babel-loader',
options: {
generatorOpts: {
compact: false
}
}
}
]
},
/* config.module.rule('css') */
{
test: /\\\\.css$/,
use: [
/* config.module.rule('css').use('apply-css-loader') */
{
loader: 'apply-css-loader'
},
/* config.module.rule('css').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('css').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-import'
]
}
}
}
]
},
/* config.module.rule('scss') */
{
test: /\\\\.scss$/,
use: [
/* config.module.rule('scss').use('apply-css-loader') */
{
loader: 'apply-css-loader'
},
/* config.module.rule('scss').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('scss').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-import'
]
}
}
},
/* config.module.rule('scss').use('sass-loader') */
{
loader: 'sass-loader'
}
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
defaultVendor: {
test: /[\\\\\\\\/]node_modules[\\\\\\\\/]/,
priority: -10,
name: 'vendor',
chunks: 'all'
}
}
},
minimizer: [
/* config.optimization.minimizer('TerserPlugin') */
new TerserPlugin(
{
terserOptions: {
compress: {
collapse_vars: false,
sequences: false
},
keep_fnames: true
}
}
)
]
},
plugins: [
/* config.plugin('ForkTsCheckerWebpackPlugin') */
new ForkTsCheckerWebpackPlugin(
{
typescript: {
memoryLimit: 4096
}
}
),
/* config.plugin('CleanWebpackPlugin') */
new CleanWebpackPlugin(
{
cleanOnceBeforeBuildPatterns: [
'__jest__/platforms/android/app/src/main/assets/app/**/*'
],
verbose: false
}
),
/* config.plugin('PlatformSuffixPlugin') */
new PlatformSuffixPlugin(
{
platform: 'android'
}
),
/* config.plugin('FilterWarningsPlugin') */
new FilterWarningsPlugin(
{
exclude: /System.import\\\\(\\\\) is deprecated/
}
),
/* config.plugin('DefinePlugin') */
new DefinePlugin(
{
__DEV__: true,
__NS_WEBPACK__: true,
__CSS_PARSER__: '\\"css-tree\\"',
__ANDROID__: true,
__IOS__: false,
'global.isAndroid': true,
'global.isIOS': false,
process: 'global.process'
}
),
/* config.plugin('CopyWebpackPlugin') */
new CopyPlugin(
{
patterns: [
{
from: 'assets/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
},
{
from: 'fonts/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
},
{
from: '**/*.+(jpg|png)',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
}
]
}
),
/* config.plugin('WatchStatePlugin') */
new WatchStatePlugin()
],
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'__jest__/src/app.js'
]
}
}"
`;
exports[`base configuration for ios 1`] = `
"{
mode: 'development',
externals: [
'package.json',
'~/package.json'
],
devtool: 'inline-source-map',
target: 'node',
output: {
path: '__jest__/platforms/ios/jest/app',
pathinfo: false,
publicPath: '',
libraryTarget: 'commonjs',
globalObject: 'global'
},
resolve: {
symlinks: true,
alias: {
'~': '__jest__/src',
'@': '__jest__/src'
},
extensions: [
'.ios.ts',
'.ts',
'.ios.js',
'.js',
'.ios.css',
'.css',
'.ios.scss',
'.scss',
'.ios.json',
'.json'
]
},
resolveLoader: {
modules: [
'node_modules/@nativescript/webpack/dist/loaders',
'node_modules'
]
},
module: {
rules: [
/* config.module.rule('ts') */
{
test: [
/\\\\.ts$/
],
use: [
/* config.module.rule('ts').use('ts-loader') */
{
loader: 'ts-loader',
options: {
transpileOnly: true,
allowTsInNodeModules: true,
compilerOptions: {
sourceMap: true,
declaration: false
},
getCustomTransformers: function () { /* omitted long function */ }
}
}
]
},
/* config.module.rule('js') */
{
test: /\\\\.js$/,
exclude: [
/node_modules/
],
use: [
/* config.module.rule('js').use('babel-loader') */
{
loader: 'babel-loader',
options: {
generatorOpts: {
compact: false
}
}
}
]
},
/* config.module.rule('css') */
{
test: /\\\\.css$/,
use: [
/* config.module.rule('css').use('apply-css-loader') */
{
loader: 'apply-css-loader'
},
/* config.module.rule('css').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('css').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-import'
]
}
}
}
]
},
/* config.module.rule('scss') */
{
test: /\\\\.scss$/,
use: [
/* config.module.rule('scss').use('apply-css-loader') */
{
loader: 'apply-css-loader'
},
/* config.module.rule('scss').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('scss').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'postcss-import'
]
}
}
},
/* config.module.rule('scss').use('sass-loader') */
{
loader: 'sass-loader'
}
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
defaultVendor: {
test: /[\\\\\\\\/]node_modules[\\\\\\\\/]/,
priority: -10,
name: 'vendor',
chunks: 'all'
}
}
},
minimizer: [
/* config.optimization.minimizer('TerserPlugin') */
new TerserPlugin(
{
terserOptions: {
compress: {
collapse_vars: true,
sequences: true
},
keep_fnames: true
}
}
)
]
},
plugins: [
/* config.plugin('ForkTsCheckerWebpackPlugin') */
new ForkTsCheckerWebpackPlugin(
{
typescript: {
memoryLimit: 4096
}
}
),
/* config.plugin('CleanWebpackPlugin') */
new CleanWebpackPlugin(
{
cleanOnceBeforeBuildPatterns: [
'__jest__/platforms/ios/jest/app/**/*'
],
verbose: false
}
),
/* config.plugin('PlatformSuffixPlugin') */
new PlatformSuffixPlugin(
{
platform: 'ios'
}
),
/* config.plugin('FilterWarningsPlugin') */
new FilterWarningsPlugin(
{
exclude: /System.import\\\\(\\\\) is deprecated/
}
),
/* config.plugin('DefinePlugin') */
new DefinePlugin(
{
__DEV__: true,
__NS_WEBPACK__: true,
__CSS_PARSER__: '\\"css-tree\\"',
__ANDROID__: false,
__IOS__: true,
'global.isAndroid': false,
'global.isIOS': true,
process: 'global.process'
}
),
/* config.plugin('CopyWebpackPlugin') */
new CopyPlugin(
{
patterns: [
{
from: 'assets/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
},
{
from: 'fonts/**',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
},
{
from: '**/*.+(jpg|png)',
context: '__jest__/src',
noErrorOnMissing: true,
globOptions: {
dot: false,
ignore: []
}
}
]
}
),
/* config.plugin('WatchStatePlugin') */
new WatchStatePlugin()
],
entry: {
bundle: [
'@nativescript/core/globals/index.js',
'__jest__/src/app.js'
],
'tns_modules/@nativescript/core/inspector_modules': [
'@nativescript/core/inspector_modules'
]
}
}"
`;

View File

@ -0,0 +1,46 @@
import Config from 'webpack-chain';
import { mockFile } from '../../scripts/jest.mockFiles';
import base from '../../src/configuration/base';
import { init } from '../../src';
describe('base configuration', () => {
const platforms = ['ios', 'android'];
for (let platform of platforms) {
it(`for ${platform}`, () => {
init({
[platform]: true,
});
expect(base(new Config()).toString()).toMatchSnapshot();
});
}
it('supports dotenv', () => {
mockFile('./.env', '');
init({
ios: true,
});
const config = base(new Config());
config.plugin('DotEnvPlugin').tap((args) => {
expect(args[0].path).toEqual('__jest__/.env');
return args;
});
expect(config.plugin('DotEnvPlugin')).toBeDefined();
});
it('supports env specific dotenv', () => {
mockFile('./.env.prod', '');
init({
ios: true,
env: 'prod',
});
const config = base(new Config());
config.plugin('DotEnvPlugin').tap((args) => {
expect(args[0].path).toEqual('__jest__/.env.prod');
return args;
});
expect(config.plugin('DotEnvPlugin')).toBeDefined();
});
});

View File

@ -27,6 +27,7 @@
"copy-webpack-plugin": "^7.0.0",
"css": "^3.0.0",
"css-loader": "^5.1.1",
"dotenv-webpack": "^6.0.2",
"fork-ts-checker-webpack-plugin": "^6.1.0",
"loader-utils": "^2.0.0",
"micromatch": "^4.0.2",

View File

@ -14,7 +14,8 @@ import { addCopyRule, applyCopyRules } from '../helpers/copyRules';
import { WatchStatePlugin } from '../plugins/WatchStatePlugin';
import { getProjectRootPath } from '../helpers/project';
import { hasDependency } from '../helpers/dependencies';
import { IWebpackEnv } from '../index';
import { applyDotEnvPlugin } from '../helpers/dotEnv';
import { env as _env, IWebpackEnv } from '../index';
import {
getPlatformName,
getAbsoluteDistPath,
@ -22,7 +23,7 @@ import {
getEntryPath,
} from '../helpers/platform';
export default function (config: Config, env: IWebpackEnv): Config {
export default function (config: Config, env: IWebpackEnv = _env): Config {
const entryPath = getEntryPath();
const platform = getPlatformName();
const mode = env.production ? 'production' : 'development';
@ -268,6 +269,9 @@ export default function (config: Config, env: IWebpackEnv): Config {
},
]);
// enable DotEnv
applyDotEnvPlugin(config);
// set up default copy rules
addCopyRule('assets/**');
addCopyRule('fonts/**');

View File

@ -0,0 +1,49 @@
import DotEnvPlugin from 'dotenv-webpack';
import Config from 'webpack-chain';
import { resolve } from 'path';
import { getProjectRootPath } from './project';
import { env } from '..';
import { existsSync } from 'fs';
/**
* @internal
*/
export function applyDotEnvPlugin(config: Config) {
const path = getDotEnvPath();
config.when(path !== null, (config) => {
config.plugin('DotEnvPlugin').use(DotEnvPlugin, [
{
path: getDotEnvPath(),
silent: true, // hide any errors
},
]);
});
}
function getDotEnvFileName(): string {
if (env.env) {
return `.env.${env.env}`;
}
return '.env';
}
function getDotEnvPath(): string {
const dotEnvPath = resolve(getProjectRootPath(), '.env');
const dotEnvWithEnvPath = resolve(getProjectRootPath(), getDotEnvFileName());
// look for .env.<env>
if (existsSync(dotEnvWithEnvPath)) {
return dotEnvWithEnvPath;
}
// fall back to .env
if (existsSync(dotEnvPath)) {
return dotEnvPath;
}
// don't use .env
return null;
}

View File

@ -12,6 +12,8 @@ import helpers from './helpers';
export interface IWebpackEnv {
[name: string]: any;
env?: string;
appPath?: string;
appResourcesPath?: string;