Skip to content

Commit 721acd5

Browse files
NativeScript 5.4 & webpack compat (preparing for NativeScript 6)
1 parent 426d198 commit 721acd5

File tree

5 files changed

+326
-9
lines changed

5 files changed

+326
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ src/*.d.ts
1313
seed-tests/seed-copy/**/*.*
1414
seed-tests/seed-copy-new-git-repo/**/*.*
1515
!demo/karma.conf.js
16+
!demo/webpack.config.js
1617
!demo/app/tests/*.js
1718
demo/*.d.ts
1819
!demo/references.d.ts

demo/nsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"useLegacyWorkflow": false
3+
}

demo/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
"nativescript": {
33
"id": "org.nativescript.demo",
44
"tns-android": {
5-
"version": "5.1.0"
5+
"version": "5.4.0"
66
},
77
"tns-ios": {
8-
"version": "5.1.1"
8+
"version": "5.4.0"
99
}
1010
},
1111
"dependencies": {
1212
"nativescript-https": "file:../src",
1313
"nativescript-theme-core": "^1.0.4",
1414
"nativescript-unit-test-runner": "^0.3.4",
15-
"tns-core-modules": "^5.1.0"
15+
"tns-core-modules": "~5.4.0"
1616
},
1717
"devDependencies": {
1818
"jasmine-core": "^2.5.2",
@@ -21,10 +21,10 @@
2121
"karma-nativescript-launcher": "^0.4.0",
2222
"nativescript-css-loader": "~0.26.1",
2323
"nativescript-dev-typescript": "~0.7.4",
24-
"nativescript-dev-webpack": "~0.17.0",
25-
"tns-platform-declarations": "^5.1.0",
24+
"nativescript-dev-webpack": "0.24.1",
25+
"tns-platform-declarations": "~5.4.0",
2626
"tslint": "~5.11.0",
27-
"typescript": "~2.8.2"
27+
"typescript": "~2.9.0"
2828
},
2929
"scripts": {
3030
"build.plugin": "cd ../src && npm run build",

demo/webpack.config.js

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
const { join, relative, resolve, sep } = require("path");
2+
3+
const webpack = require("webpack");
4+
const nsWebpack = require("nativescript-dev-webpack");
5+
const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target");
6+
const CleanWebpackPlugin = require("clean-webpack-plugin");
7+
const CopyWebpackPlugin = require("copy-webpack-plugin");
8+
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
9+
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
10+
const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin");
11+
const TerserPlugin = require("terser-webpack-plugin");
12+
const hashSalt = Date.now().toString();
13+
14+
module.exports = env => {
15+
// Add your custom Activities, Services and other Android app components here.
16+
const appComponents = [
17+
"tns-core-modules/ui/frame",
18+
"tns-core-modules/ui/frame/activity",
19+
];
20+
21+
const platform = env && (env.android && "android" || env.ios && "ios");
22+
if (!platform) {
23+
throw new Error("You need to provide a target platform!");
24+
}
25+
26+
const platforms = ["ios", "android"];
27+
const projectRoot = __dirname;
28+
29+
// Default destination inside platforms/<platform>/...
30+
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
31+
const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";
32+
33+
const {
34+
// The 'appPath' and 'appResourcesPath' values are fetched from
35+
// the nsconfig.json configuration file
36+
// when bundling with `tns run android|ios --bundle`.
37+
appPath = "app",
38+
appResourcesPath = "app/App_Resources",
39+
40+
// You can provide the following flags when running 'tns run android|ios'
41+
snapshot, // --env.snapshot
42+
uglify, // --env.uglify
43+
report, // --env.report
44+
sourceMap, // --env.sourceMap
45+
hiddenSourceMap, // --env.hiddenSourceMap
46+
hmr, // --env.hmr,
47+
unitTesting, // --env.unitTesting
48+
} = env;
49+
const isAnySourceMapEnabled = !!sourceMap || !!hiddenSourceMap;
50+
const externals = nsWebpack.getConvertedExternals(env.externals);
51+
52+
const appFullPath = resolve(projectRoot, appPath);
53+
const appResourcesFullPath = resolve(projectRoot, appResourcesPath);
54+
55+
const entryModule = nsWebpack.getEntryModule(appFullPath, platform);
56+
const entryPath = `.${sep}${entryModule}.ts`;
57+
const entries = { bundle: entryPath };
58+
59+
const tsConfigPath = resolve(projectRoot, "tsconfig.tns.json");
60+
61+
if (platform === "ios") {
62+
entries["tns_modules/tns-core-modules/inspector_modules"] = "inspector_modules.js";
63+
};
64+
65+
let sourceMapFilename = nsWebpack.getSourceMapFilename(hiddenSourceMap, __dirname, dist);
66+
67+
const config = {
68+
mode: uglify ? "production" : "development",
69+
context: appFullPath,
70+
externals,
71+
watchOptions: {
72+
ignored: [
73+
appResourcesFullPath,
74+
// Don't watch hidden files
75+
"**/.*",
76+
]
77+
},
78+
target: nativescriptTarget,
79+
entry: entries,
80+
output: {
81+
pathinfo: false,
82+
path: dist,
83+
sourceMapFilename,
84+
libraryTarget: "commonjs2",
85+
filename: "[name].js",
86+
globalObject: "global",
87+
hashSalt
88+
},
89+
resolve: {
90+
extensions: [".ts", ".js", ".scss", ".css"],
91+
// Resolve {N} system modules from tns-core-modules
92+
modules: [
93+
resolve(__dirname, "node_modules/tns-core-modules"),
94+
resolve(__dirname, "node_modules"),
95+
"node_modules/tns-core-modules",
96+
"node_modules",
97+
],
98+
alias: {
99+
'~': appFullPath
100+
},
101+
// resolve symlinks to symlinked modules
102+
symlinks: true
103+
},
104+
resolveLoader: {
105+
// don't resolve symlinks to symlinked loaders
106+
symlinks: false
107+
},
108+
node: {
109+
// Disable node shims that conflict with NativeScript
110+
"http": false,
111+
"timers": false,
112+
"setImmediate": false,
113+
"fs": "empty",
114+
"__dirname": false,
115+
},
116+
devtool: hiddenSourceMap ? "hidden-source-map" : (sourceMap ? "inline-source-map" : "none"),
117+
optimization: {
118+
runtimeChunk: "single",
119+
splitChunks: {
120+
cacheGroups: {
121+
vendor: {
122+
name: "vendor",
123+
chunks: "all",
124+
test: (module, chunks) => {
125+
const moduleName = module.nameForCondition ? module.nameForCondition() : '';
126+
return /[\\/]node_modules[\\/]/.test(moduleName) ||
127+
appComponents.some(comp => comp === moduleName);
128+
129+
},
130+
enforce: true,
131+
},
132+
}
133+
},
134+
minimize: !!uglify,
135+
minimizer: [
136+
new TerserPlugin({
137+
parallel: true,
138+
cache: true,
139+
sourceMap: isAnySourceMapEnabled,
140+
terserOptions: {
141+
output: {
142+
comments: false,
143+
semicolons: !isAnySourceMapEnabled
144+
},
145+
compress: {
146+
// The Android SBG has problems parsing the output
147+
// when these options are enabled
148+
'collapse_vars': platform !== "android",
149+
sequences: platform !== "android",
150+
}
151+
}
152+
})
153+
],
154+
},
155+
module: {
156+
rules: [
157+
{
158+
test: nsWebpack.getEntryPathRegExp(appFullPath, entryPath),
159+
use: [
160+
// Require all Android app components
161+
platform === "android" && {
162+
loader: "nativescript-dev-webpack/android-app-components-loader",
163+
options: { modules: appComponents }
164+
},
165+
166+
{
167+
loader: "nativescript-dev-webpack/bundle-config-loader",
168+
options: {
169+
loadCss: !snapshot, // load the application css if in debug mode
170+
unitTesting,
171+
appFullPath,
172+
projectRoot,
173+
}
174+
},
175+
].filter(loader => !!loader)
176+
},
177+
178+
{
179+
test: /-page\.ts$/,
180+
use: "nativescript-dev-webpack/script-hot-loader"
181+
},
182+
183+
{
184+
test: /\.(css|scss)$/,
185+
use: "nativescript-dev-webpack/style-hot-loader"
186+
},
187+
188+
{
189+
test: /\.(html|xml)$/,
190+
use: "nativescript-dev-webpack/markup-hot-loader"
191+
},
192+
193+
{ test: /\.(html|xml)$/, use: "nativescript-dev-webpack/xml-namespace-loader" },
194+
195+
{
196+
test: /\.css$/,
197+
use: { loader: "css-loader", options: { url: false } }
198+
},
199+
200+
{
201+
test: /\.scss$/,
202+
use: [
203+
{ loader: "css-loader", options: { url: false } },
204+
"sass-loader"
205+
]
206+
},
207+
208+
{
209+
test: /\.ts$/,
210+
use: {
211+
loader: "ts-loader",
212+
options: {
213+
configFile: tsConfigPath,
214+
// https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds
215+
// https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#hot-module-replacement
216+
transpileOnly: true,
217+
allowTsInNodeModules: true,
218+
compilerOptions: {
219+
sourceMap: isAnySourceMapEnabled,
220+
declaration: false
221+
}
222+
},
223+
}
224+
},
225+
]
226+
},
227+
plugins: [
228+
// Define useful constants like TNS_WEBPACK
229+
new webpack.DefinePlugin({
230+
"global.TNS_WEBPACK": "true",
231+
"process": undefined,
232+
}),
233+
// Remove all files from the out dir.
234+
new CleanWebpackPlugin([`${dist}/**/*`]),
235+
// Copy assets to out dir. Add your own globs as needed.
236+
new CopyWebpackPlugin([
237+
{ from: { glob: "fonts/**" } },
238+
{ from: { glob: "**/*.jpg" } },
239+
{ from: { glob: "**/*.png" } },
240+
{ from: { glob: "assets/*.cer" } },
241+
], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
242+
// Generate a bundle starter script and activate it in package.json
243+
new nsWebpack.GenerateBundleStarterPlugin(
244+
// Don't include `runtime.js` when creating a snapshot. The plugin
245+
// configures the WebPack runtime to be generated inside the snapshot
246+
// module and no `runtime.js` module exist.
247+
(snapshot ? [] : ["./runtime"])
248+
.concat([
249+
"./vendor",
250+
"./bundle",
251+
])
252+
),
253+
// For instructions on how to set up workers with webpack
254+
// check out https://github.com/nativescript/worker-loader
255+
new NativeScriptWorkerPlugin(),
256+
new nsWebpack.PlatformFSPlugin({
257+
platform,
258+
platforms,
259+
}),
260+
// Does IPC communication with the {N} CLI to notify events when running in watch mode.
261+
new nsWebpack.WatchStateLoggerPlugin(),
262+
// https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#faster-builds
263+
// https://github.com/TypeStrong/ts-loader/blob/ea2fcf925ec158d0a536d1e766adfec6567f5fb4/README.md#hot-module-replacement
264+
new ForkTsCheckerWebpackPlugin({
265+
tsconfig: tsConfigPath,
266+
async: false,
267+
useTypescriptIncrementalApi: true,
268+
memoryLimit: 4096
269+
})
270+
],
271+
};
272+
273+
// Copy the native app resources to the out dir
274+
// only if doing a full build (tns run/build) and not previewing (tns preview)
275+
if (!externals || externals.length === 0) {
276+
config.plugins.push(new CopyWebpackPlugin([
277+
{
278+
from: `${appResourcesFullPath}/${appResourcesPlatformDir}`,
279+
to: `${dist}/App_Resources/${appResourcesPlatformDir}`,
280+
context: projectRoot
281+
},
282+
]));
283+
}
284+
285+
if (report) {
286+
// Generate report files for bundles content
287+
config.plugins.push(new BundleAnalyzerPlugin({
288+
analyzerMode: "static",
289+
openAnalyzer: false,
290+
generateStatsFile: true,
291+
reportFilename: resolve(projectRoot, "report", `report.html`),
292+
statsFilename: resolve(projectRoot, "report", `stats.json`),
293+
}));
294+
}
295+
296+
if (snapshot) {
297+
config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
298+
chunk: "vendor",
299+
requireModules: [
300+
"tns-core-modules/bundle-entry-points",
301+
],
302+
projectRoot,
303+
webpackConfig: config,
304+
}));
305+
}
306+
307+
if (hmr) {
308+
config.plugins.push(new webpack.HotModuleReplacementPlugin());
309+
}
310+
311+
312+
return config;
313+
};

src/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
},
3030
"dependencies": {},
3131
"devDependencies": {
32-
"tns-core-modules": "^5.1.0",
33-
"tns-platform-declarations": "^5.1.0",
34-
"typescript": "~2.8.2",
32+
"tns-core-modules": "~5.4.0",
33+
"tns-platform-declarations": "~5.4.0",
34+
"typescript": "~2.9.0",
3535
"prompt": "^1.0.0",
3636
"rimraf": "^2.6.2",
3737
"tslint": "^5.11.0",

0 commit comments

Comments
 (0)