chore: more base configuration

This commit is contained in:
Igor Randjelovic
2020-11-17 14:49:36 +01:00
parent b22e1c2361
commit bea55474df
7 changed files with 328 additions and 42 deletions

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`vue configuration [android] works 1`] = ` exports[`vue configuration for android 1`] = `
"{ "{
resolve: { resolve: {
symlinks: true, symlinks: true,
@ -14,8 +14,74 @@ exports[`vue configuration [android] works 1`] = `
'.vue' '.vue'
] ]
}, },
resolveLoader: {
modules: [
'@nativescript/webpack/loaders',
'node_modules'
]
},
module: { module: {
rules: [ 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 */ },
appendTsSuffixTo: [
'\\\\\\\\.vue$'
]
}
}
]
},
/* config.module.rule('js') */
{
test: /\\\\.js$/,
use: [
/* config.module.rule('js').use('babel-loader') */
{
loader: 'babel-loader'
}
]
},
/* config.module.rule('css') */
{
test: /\\\\.css$/,
use: [
/* config.module.rule('css').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('css').use('css-loader') */
{
loader: 'css-loader'
}
]
},
/* config.module.rule('scss') */
{
test: /\\\\.scss$/,
use: [
/* config.module.rule('scss').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('scss').use('scss-loader') */
{
loader: 'scss-loader'
}
]
},
/* config.module.rule('vue') */ /* config.module.rule('vue') */
{ {
test: /\\\\.vue$/, test: /\\\\.vue$/,
@ -28,20 +94,6 @@ exports[`vue configuration [android] works 1`] = `
} }
} }
] ]
},
/* config.module.rule('ts') */
{
use: [
/* config.module.rule('ts').use('ts-loader') */
{
loader: 'ts-loader',
options: {
appendTsSuffixTo: [
/\\\\.vue$/
]
}
}
]
} }
] ]
}, },
@ -55,7 +107,24 @@ exports[`vue configuration [android] works 1`] = `
verbose: true verbose: true
} }
), ),
/* config.plugin('vue-plugin') */ /* config.plugin('define') */
new DefinePlugin(
{
'global.NS_WEBPACK': true,
'global.isAndroid': true,
'global.isIOS': false,
process: 'global.process'
}
),
/* config.plugin('copy') */
new CopyPluginTemp(
{
patterns: []
}
),
/* config.plugin('watch-state-logger') */
new WatchStateLoggerPlugin(),
/* config.plugin('vue') */
new VueLoaderPlugin() new VueLoaderPlugin()
], ],
entry: { entry: {
@ -66,7 +135,7 @@ exports[`vue configuration [android] works 1`] = `
}" }"
`; `;
exports[`vue configuration [ios] works 1`] = ` exports[`vue configuration for ios 1`] = `
"{ "{
resolve: { resolve: {
symlinks: true, symlinks: true,
@ -80,8 +149,74 @@ exports[`vue configuration [ios] works 1`] = `
'.vue' '.vue'
] ]
}, },
resolveLoader: {
modules: [
'@nativescript/webpack/loaders',
'node_modules'
]
},
module: { module: {
rules: [ 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 */ },
appendTsSuffixTo: [
'\\\\\\\\.vue$'
]
}
}
]
},
/* config.module.rule('js') */
{
test: /\\\\.js$/,
use: [
/* config.module.rule('js').use('babel-loader') */
{
loader: 'babel-loader'
}
]
},
/* config.module.rule('css') */
{
test: /\\\\.css$/,
use: [
/* config.module.rule('css').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('css').use('css-loader') */
{
loader: 'css-loader'
}
]
},
/* config.module.rule('scss') */
{
test: /\\\\.scss$/,
use: [
/* config.module.rule('scss').use('css2json-loader') */
{
loader: 'css2json-loader'
},
/* config.module.rule('scss').use('scss-loader') */
{
loader: 'scss-loader'
}
]
},
/* config.module.rule('vue') */ /* config.module.rule('vue') */
{ {
test: /\\\\.vue$/, test: /\\\\.vue$/,
@ -94,20 +229,6 @@ exports[`vue configuration [ios] works 1`] = `
} }
} }
] ]
},
/* config.module.rule('ts') */
{
use: [
/* config.module.rule('ts').use('ts-loader') */
{
loader: 'ts-loader',
options: {
appendTsSuffixTo: [
/\\\\.vue$/
]
}
}
]
} }
] ]
}, },
@ -121,7 +242,24 @@ exports[`vue configuration [ios] works 1`] = `
verbose: true verbose: true
} }
), ),
/* config.plugin('vue-plugin') */ /* config.plugin('define') */
new DefinePlugin(
{
'global.NS_WEBPACK': true,
'global.isAndroid': false,
'global.isIOS': true,
process: 'global.process'
}
),
/* config.plugin('copy') */
new CopyPluginTemp(
{
patterns: []
}
),
/* config.plugin('watch-state-logger') */
new WatchStateLoggerPlugin(),
/* config.plugin('vue') */
new VueLoaderPlugin() new VueLoaderPlugin()
], ],
entry: { entry: {

View File

@ -1,10 +1,16 @@
import { __vue } from '@nativescript/webpack'; import { __vue } from '@nativescript/webpack';
// todo: maybe mock baseConfig as we test it separately?
// import Config from 'webpack-chain'
// jest.mock('../../src/configuration/base', () => () => {
// return new Config()
// })
describe('vue configuration', () => { describe('vue configuration', () => {
const platforms = ['ios', 'android']; const platforms = ['ios', 'android'];
for (let platform of platforms) { for (let platform of platforms) {
it(`[${platform}] works`, () => { it(`for ${platform}`, () => {
expect( expect(
__vue({ __vue({
[platform]: true, [platform]: true,

View File

@ -18,6 +18,7 @@
"dependencies": { "dependencies": {
"clean-webpack-plugin": "^3.0.0", "clean-webpack-plugin": "^3.0.0",
"vue-loader": "^15.9.5", "vue-loader": "^15.9.5",
"webpack-chain": "^6.5.1" "webpack-chain": "^6.5.1",
"webpack-merge": "^5.4.0"
} }
} }

View File

@ -2,11 +2,19 @@ import Config from 'webpack-chain';
import { IWebpackEnv, WebpackPlatform } from './index'; import { IWebpackEnv, WebpackPlatform } from './index';
import { CleanWebpackPlugin } from 'clean-webpack-plugin'; import { CleanWebpackPlugin } from 'clean-webpack-plugin';
import { getDistPath } from '../helpers/projectHelpers'; import { getDistPath } from '../helpers/projectHelpers';
import { DefinePlugin } from 'webpack';
import { WatchStateLoggerPlugin } from '../plugins/WatchStateLoggerPlugin';
// todo: add base configuration that's shared across all flavors // todo: add base configuration that's shared across all flavors
export default function (env: IWebpackEnv): Config { export default function (env: IWebpackEnv): Config {
const config = new Config(); const config = new Config();
const distPath = getDistPath(env); const distPath = getDistPath(env);
const platform = determinePlatformFromEnv(env);
// look for loaders in
// - @nativescript/webpack/loaders
// - node_modules
config.resolveLoader.modules.add('@nativescript/webpack/loaders').add('node_modules');
// inspector_modules // inspector_modules
config.when(shouldIncludeInspectorModules(env), (config) => { config.when(shouldIncludeInspectorModules(env), (config) => {
@ -21,6 +29,53 @@ export default function (env: IWebpackEnv): Config {
// resolve symlinks // resolve symlinks
config.resolve.symlinks(true); config.resolve.symlinks(true);
// set up ts support
config.module
.rule('ts')
.test(/\.ts$/)
.use('ts-loader')
.loader('ts-loader')
.options({
// configFile: '',
transpileOnly: true,
allowTsInNodeModules: true,
compilerOptions: {
sourceMap: true,
declaration: false,
},
getCustomTransformers() {
return {
before: [
// todo: transform NativeClass
],
};
},
});
// set up js
// todo: do we need babel-loader? It's useful to support it
config.module.rule('js').test(/\.js$/).use('babel-loader').loader('babel-loader');
// set up css
config.module
.rule('css')
.test(/\.css$/)
.use('css2json-loader')
.loader('css2json-loader')
.end()
.use('css-loader')
.loader('css-loader');
// set up scss
config.module
.rule('scss')
.test(/\.scss$/)
.use('css2json-loader')
.loader('css2json-loader')
.end()
.use('scss-loader')
.loader('scss-loader');
// items to clean // items to clean
config.plugin('clean').use(CleanWebpackPlugin, [ config.plugin('clean').use(CleanWebpackPlugin, [
{ {
@ -29,6 +84,28 @@ export default function (env: IWebpackEnv): Config {
}, },
]); ]);
// todo: refine defaults
config.plugin('define').use(DefinePlugin, [
{
'global.NS_WEBPACK': true,
'global.isAndroid': platform === WebpackPlatform.android,
'global.isIOS': platform === WebpackPlatform.ios,
process: 'global.process',
},
]);
// todo: we should probably move away from CopyWebpackPlugin
// it has many issues we can solve by simply copying files **before** the build even starts
// this is just a temp inline plugin that does nothing while building out the configs.
config.plugin('copy').use(function CopyPluginTemp() {}, [
{
patterns: [],
},
]);
// add the WatchStateLogger plugin used to notify the CLI of build state
config.plugin('watch-state-logger').use(WatchStateLoggerPlugin);
return config; return config;
} }

View File

@ -2,9 +2,16 @@ import base from './base';
import { IWebpackEnv } from '@nativescript/webpack'; import { IWebpackEnv } from '@nativescript/webpack';
import Config from 'webpack-chain'; import Config from 'webpack-chain';
// todo: add base configuration for core // todo: add base configuration for core with javascript
export default function (env: IWebpackEnv): Config { export default function (env: IWebpackEnv): Config {
const config = base(env); const config = base(env);
// set up xml
config.module
.rule('xml')
.test(/\.xml$/)
.use('xml-loader')
.loader('xml-loader');
return config; return config;
} }

View File

@ -2,7 +2,7 @@ import base from './base';
import Config from 'webpack-chain'; import Config from 'webpack-chain';
import { VueLoaderPlugin } from 'vue-loader'; import { VueLoaderPlugin } from 'vue-loader';
import { IWebpackEnv } from './index'; import { IWebpackEnv } from './index';
import { merge } from 'webpack-merge';
// todo: add base configuration for vue // todo: add base configuration for vue
export default function (env: IWebpackEnv): Config { export default function (env: IWebpackEnv): Config {
const config = base(env); const config = base(env);
@ -29,15 +29,14 @@ export default function (env: IWebpackEnv): Config {
.rule('ts') .rule('ts')
.use('ts-loader') .use('ts-loader')
.loader('ts-loader') .loader('ts-loader')
.tap((options) => { .tap((options = {}) => {
return { return merge(options, {
...options, appendTsSuffixTo: ['\\.vue$'],
appendTsSuffixTo: [/\.vue$/], });
};
}); });
// add VueLoaderPlugin // add VueLoaderPlugin
config.plugin('vue-plugin').use(VueLoaderPlugin); config.plugin('vue').use(VueLoaderPlugin);
// add an alias for vue, since some plugins may try to import it // add an alias for vue, since some plugins may try to import it
config.resolve.alias.set('vue', 'nativescript-vue'); config.resolve.alias.set('vue', 'nativescript-vue');

View File

@ -0,0 +1,58 @@
export enum messages {
compilationComplete = 'Webpack compilation complete.',
startWatching = 'Webpack compilation complete. Watching for file changes.',
changeDetected = 'File change detected. Starting incremental webpack compilation...',
}
/**
* This little plugin will report the webpack state through the console.
* So the {N} CLI can get some idea when compilation completes.
*/
export class WatchStateLoggerPlugin {
isRunningWatching: boolean;
apply(compiler) {
const plugin = this;
compiler.hooks.watchRun.tapAsync('WatchStateLoggerPlugin', function (compiler, callback) {
plugin.isRunningWatching = true;
if (plugin.isRunningWatching) {
console.log(messages.changeDetected);
}
process.send && process.send(messages.changeDetected, (error) => null);
callback();
});
compiler.hooks.afterEmit.tapAsync('WatchStateLoggerPlugin', function (compilation, callback) {
callback();
if (plugin.isRunningWatching) {
console.log(messages.startWatching);
} else {
console.log(messages.compilationComplete);
}
const emittedFiles = Object.keys(compilation.assets).filter((assetKey) => compilation.assets[assetKey].emitted);
const chunkFiles = getChunkFiles(compilation);
process.send && process.send(messages.compilationComplete, (error) => null);
// Send emitted files so they can be LiveSynced if need be
process.send && process.send({ emittedFiles, chunkFiles, hash: compilation.hash }, (error) => null);
});
}
}
function getChunkFiles(compilation) {
const chunkFiles = [];
try {
compilation.chunks.forEach((chunk) => {
chunk.files.forEach((file) => {
if (file.indexOf('hot-update') === -1) {
chunkFiles.push(file);
}
});
});
} catch (e) {
console.log('Warning: Unable to find chunk files.');
}
return chunkFiles;
}