Skip to content

Commit 6cb6099

Browse files
committed
fix(): missing webpack config
1 parent 63fd3b9 commit 6cb6099

File tree

2 files changed

+350
-0
lines changed

2 files changed

+350
-0
lines changed

apps/demo/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ platforms/
66
# NativeScript Template
77
*.js.map
88
*.js
9+
!webpack.config.js
910

1011
# Logs
1112
logs

apps/demo/webpack.config.js

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

0 commit comments

Comments
 (0)