├── .babelrc ├── JsComponent.js ├── LICENSE ├── README.md ├── VueComponent.vue ├── app.css ├── app.js ├── app.scss ├── images ├── apple.jpg └── vue.png ├── package.json ├── postinstall.js ├── tns └── app │ ├── app.css │ ├── app.js │ └── package.json ├── vendor-platform.android.js ├── vendor-platform.ios.js ├── vendor.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "es2015", 5 | { 6 | "modules": false 7 | } 8 | ], 9 | "stage-2" 10 | ] 11 | } -------------------------------------------------------------------------------- /JsComponent.js: -------------------------------------------------------------------------------- 1 | export default { 2 | template: ` 3 | 4 | ` 5 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Tiago Alves 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED!!! 2 | This template is being deprecated in favor of the [Vue Cli template](https://github.com/nativescript-vue/vue-cli-template). There are some serious problems that `vue-cli` simply deals with much nicely. 3 | 4 | # NativeScript Vue.js Template 5 | 6 | This repo serves as the starting point for NativeScript + Vue.js projects, using [nativescript-vue](https://github.com/rigor789/nativescript-vue). 7 | 8 | This template creates a project ready to use with Vue single file components\* (`.vue` files)! 9 | 10 | ## Usage 11 | 12 | 1. Install NativeScript tools (see http://docs.nativescript.org/start/quick-setup) 13 | 14 | 2. Create app from this template 15 | ```bash 16 | tns create hello-ns-vue --template https://github.com/tralves/nativescript-vue-webpack-template 17 | ``` 18 | 19 | 3. Watch for changes while developing 20 | 21 | In two separate terminals run: 22 | ```bash 23 | # terminal 1 24 | webpack --watch --env.tns --env.android 25 | # or 26 | webpack --watch --env.tns --env.ios 27 | 28 | # terminal 2 29 | cd tns && tns debug android 30 | # or 31 | cd tns && tns debug ios 32 | ``` 33 | 34 | 4. Bundle Android or iOS for deploy (see: [{NS} documentation on webpack bundling](https://docs.nativescript.org/tooling/bundling-with-webpack#bundling)) 35 | ```bash 36 | npm run start-android-bundle -- --clean 37 | npm run start-ios-bundle -- --clean 38 | ``` 39 | 40 | 5. Code! 41 | You will find more sample code [here](https://github.com/tralves/nativescript-vue/tree/master/samples). 42 | -------------------------------------------------------------------------------- /VueComponent.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | 15 | 22 | 23 | -------------------------------------------------------------------------------- /app.css: -------------------------------------------------------------------------------- 1 | @import 'nativescript-theme-core/css/core.light.css'; 2 | 3 | /* Your CSS goes here */ 4 | 5 | .even { 6 | color: red; 7 | } 8 | 9 | .odd { 10 | color: blue; 11 | } -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const Vue = require('nativescript-vue/dist/index') 2 | const http = require("http") 3 | 4 | import JsComponent from './JsComponent'; 5 | import VueComponent from './VueComponent'; 6 | 7 | import './app.scss' 8 | 9 | Vue.prototype.$http = http 10 | 11 | new Vue({ 12 | components: { 13 | JsComponent, 14 | VueComponent 15 | }, 16 | 17 | template: ` 18 | 19 | 20 | 21 | 22 | 23 | 24 | `, 25 | methods: { 26 | } 27 | }).$start() -------------------------------------------------------------------------------- /app.scss: -------------------------------------------------------------------------------- 1 | $main-color : blue; 2 | 3 | label{ 4 | color : $main-color; 5 | } -------------------------------------------------------------------------------- /images/apple.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tralves/nativescript-vue-webpack-template/3a7247abe7c211c6a4dee11d83fa3c97997604a5/images/apple.jpg -------------------------------------------------------------------------------- /images/vue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tralves/nativescript-vue-webpack-template/3a7247abe7c211c6a4dee11d83fa3c97997604a5/images/vue.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "app.js", 3 | "name": "nativescript-vue-webpack", 4 | "version": "0.1.0", 5 | "description": "NativeScript Vue Application", 6 | "license": "SEE LICENSE IN LICENSE", 7 | "readme": "README.md", 8 | "repository": "https://github.com/tralves/nativescript-vue-webpack-template", 9 | "dependencies": { 10 | "nativescript-theme-core": "~1.0.4", 11 | "nativescript-vue": "^1.0.0", 12 | "tns-core-modules": "^3.4.0" 13 | }, 14 | "devDependencies": { 15 | "babel-core": "^6.26.0", 16 | "babel-loader": "^7.1.2", 17 | "babel-preset-es2015": "^6.24.1", 18 | "babel-preset-stage-2": "^6.24.1", 19 | "babel-traverse": "6.24.1", 20 | "babel-types": "6.24.1", 21 | "babylon": "6.16.1", 22 | "copy-webpack-plugin": "~4.0.1", 23 | "css-loader": "^0.28.4", 24 | "extract-text-webpack-plugin": "~2.1.0", 25 | "lazy": "1.0.11", 26 | "merge-files-webpack-plugin": "^1.1.2", 27 | "nativescript-css-loader": "~0.26.0", 28 | "nativescript-dev-android-snapshot": "^0.*.*", 29 | "nativescript-dev-webpack": "^0.6.3", 30 | "node-sass": "^4.5.3", 31 | "ns-vue-loader": "^0.1.0", 32 | "raw-loader": "~0.5.1", 33 | "resolve-url-loader": "~2.0.2", 34 | "sass-loader": "^6.0.6", 35 | "style-loader": "^0.18.2", 36 | "vue-loader": "^12.2.1", 37 | "vue-style-loader": "^3.0.1", 38 | "vue-template-compiler": "^2.5.2", 39 | "webpack": "~2.6.1", 40 | "webpack-sources": "~1.0.1" 41 | }, 42 | "scripts": { 43 | "ns-bundle": "ns-bundle", 44 | "publish-ios-bundle": "npm run ns-bundle --ios --publish-app", 45 | "start-android-bundle": "npm run ns-bundle --android --run-app", 46 | "start-ios-bundle": "npm run ns-bundle --ios --run-app", 47 | "build-android-bundle": "npm run ns-bundle --android --build-app", 48 | "build-ios-bundle": "npm run ns-bundle --ios --build-app", 49 | "watch-android-bundle": "webpack --watch --env.tns --env.android", 50 | "watch-ios-bundle": "webpack --watch --env.tns --env.ios", 51 | "postinstall": "node postinstall.js" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /postinstall.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | move(getMovePaths('webpack.config.js'), log); 5 | move(getMovePaths('.babelrc'), log); 6 | move(getMovePaths('tns'), log); 7 | 8 | console.log('listing files'); 9 | fs.readdirSync(path.join(__dirname, '..', '..', 'tns')).forEach(file => { 10 | console.log(file); 11 | }) 12 | 13 | symlinkFromTns('package.json', 'file'); 14 | symlinkFromTns('package-lock.json', 'file'); 15 | symlinkFromTns('node_modules', 'dir'); 16 | symlinkFromTns('app/App_Resources', 'dir'); 17 | symlinkFromTns('app/images', 'dir'); 18 | 19 | fs.unlinkSync('postinstall.js'); 20 | 21 | function getMovePaths(movingFile) { 22 | return { 23 | oldPath: path.join(__dirname, movingFile), 24 | newPath: path.join(__dirname, '..', '..', movingFile) 25 | } 26 | } 27 | 28 | function log(err) { 29 | if (err) { 30 | console.log(err); 31 | } 32 | } 33 | 34 | function symlinkFromTns(file, type) { 35 | console.log('linking ', path.join(__dirname, '..', '..', file), path.join(__dirname, '..', '..', 'tns', file)); 36 | 37 | if (fs.existsSync(path.join(__dirname, '..', '..', 'tns', file))) { 38 | fs.unlinkSync(path.join(__dirname, '..', '..', 'tns', file)); 39 | } 40 | fs.symlinkSync( 41 | path.join(__dirname, '..', '..', file), 42 | path.join(__dirname, '..', '..', 'tns', file), 43 | type); 44 | } 45 | 46 | // move function copied from: https://stackoverflow.com/questions/8579055/how-i-move-files-on-node-js 47 | function move({ oldPath, newPath }, callback) { 48 | fs.rename(oldPath, newPath, function (err) { 49 | if (err) { 50 | if (err.code === 'EXDEV') { 51 | copy(); 52 | } else { 53 | callback(err); 54 | } 55 | return; 56 | } 57 | callback(); 58 | }); 59 | 60 | function copy() { 61 | var readStream = fs.createReadStream(oldPath); 62 | var writeStream = fs.createWriteStream(newPath); 63 | 64 | readStream.on('error', callback); 65 | writeStream.on('error', callback); 66 | 67 | readStream.on('close', function () { 68 | fs.unlink(oldPath, callback); 69 | }); 70 | 71 | readStream.pipe(writeStream); 72 | } 73 | } -------------------------------------------------------------------------------- /tns/app/app.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | label[data-v-45ba5ed4] { 33 | text-align: center; 34 | font-size: 25; 35 | } 36 | 37 | Button[data-v-45ba5ed4] { 38 | background-color: #00caab; 39 | } 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | .large[data-v-303c0480] { 70 | font-size: 40; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /tns/app/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } 4 | 5 | var Vue = _interopDefault(require('nativescript-vue')); 6 | 7 | var TestComponent = { template: "",_scopeId: 'data-v-303c0480', 8 | 9 | data() { 10 | return { 11 | name: 'John', 12 | age: 34, 13 | occupation: 'Developer' 14 | } 15 | } 16 | }; 17 | 18 | var App = { template: "",_scopeId: 'data-v-45ba5ed4', 19 | 20 | data() { 21 | return { 22 | count: 10 23 | } 24 | }, 25 | 26 | components: { 27 | TestComponent 28 | } 29 | }; 30 | 31 | new Vue({ 32 | render: h => h('app'), 33 | components: { 34 | App 35 | } 36 | }).$start(); 37 | -------------------------------------------------------------------------------- /tns/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "android": { 3 | "v8Flags": "--expose_gc" 4 | }, 5 | "main": "app.js", 6 | "name": "tns-template-hello-world", 7 | "version": "3.2.0" 8 | } -------------------------------------------------------------------------------- /vendor-platform.android.js: -------------------------------------------------------------------------------- 1 | require("application"); 2 | require("ui/frame"); 3 | require("ui/frame/activity"); 4 | -------------------------------------------------------------------------------- /vendor-platform.ios.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tralves/nativescript-vue-webpack-template/3a7247abe7c211c6a4dee11d83fa3c97997604a5/vendor-platform.ios.js -------------------------------------------------------------------------------- /vendor.js: -------------------------------------------------------------------------------- 1 | require("./vendor-platform"); 2 | require('nativescript-vue/dist/index'); 3 | 4 | require("bundle-entry-points"); 5 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const { resolve, join } = 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 CopyWebpackPlugin = require("copy-webpack-plugin"); 7 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 8 | var MergeFilesPlugin = require('merge-files-webpack-plugin'); 9 | 10 | const extractMainSheet = new ExtractTextPlugin('app-0.css'); 11 | const extractCSS = new ExtractTextPlugin('app-1.css'); 12 | 13 | const mainSheet = `app.css`; 14 | 15 | module.exports = env => { 16 | const platform = getPlatform(env); 17 | 18 | // tns/app -or- default destination inside platforms//... 19 | const path = env.tns ? resolve('tns/app') : resolve(nsWebpack.getAppPath(platform)); 20 | 21 | const entry = { 22 | // Discover entry module from package.json 23 | bundle: `./${nsWebpack.getEntryModule()}`, 24 | 25 | // Vendor entry with third-party libraries 26 | vendor: `./vendor`, 27 | 28 | // Entry for stylesheet with global application styles 29 | [mainSheet]: `./${mainSheet}`, 30 | }; 31 | 32 | const rules = getRules(); 33 | const plugins = getPlugins(platform, env); 34 | const extensions = getExtensions(platform); 35 | 36 | return { 37 | context: resolve("./app"), 38 | target: nativescriptTarget, 39 | entry, 40 | output: { 41 | pathinfo: true, 42 | path, 43 | libraryTarget: "commonjs2", 44 | filename: "[name].js", 45 | }, 46 | resolve: { 47 | extensions, 48 | alias: { 49 | '~': join(__dirname, 'tns', 'app') 50 | }, 51 | 52 | // Resolve {N} system modules from tns-core-modules 53 | modules: [ 54 | "node_modules/tns-core-modules", 55 | "node_modules", 56 | ] 57 | }, 58 | node: { 59 | // Disable node shims that conflict with NativeScript 60 | "http": false, 61 | "timers": false, 62 | "setImmediate": false, 63 | "fs": "empty", 64 | }, 65 | module: { rules }, 66 | plugins, 67 | }; 68 | }; 69 | 70 | function getPlatform(env) { 71 | return env.android ? "android" : 72 | env.ios ? "ios" : 73 | () => { throw new Error("You need to provide a target platform!") }; 74 | } 75 | 76 | function getRules() { 77 | return [ 78 | { 79 | test: /\.js$/, 80 | loader: 'babel-loader', 81 | include: [resolve('app')] 82 | }, 83 | { 84 | test: /\.html$|\.xml$/, 85 | use: [ 86 | "raw-loader", 87 | ] 88 | }, 89 | // Root stylesheet gets extracted with bundled dependencies 90 | { 91 | test: new RegExp(mainSheet), 92 | loader: extractMainSheet.extract([ 93 | { 94 | loader: "resolve-url-loader", 95 | options: { silent: true }, 96 | }, 97 | { 98 | loader: "nativescript-css-loader", 99 | options: { minimize: false } 100 | }, 101 | "nativescript-dev-webpack/platform-css-loader", 102 | ]), 103 | }, 104 | // Other CSS files get bundled using the raw loader 105 | { 106 | test: /\.css$/, 107 | exclude: new RegExp(mainSheet), 108 | loader: extractCSS.extract({ 109 | fallback: 'style-loader', 110 | use: { 111 | loader: 'css-loader', 112 | options: { url: false } 113 | } 114 | }) 115 | 116 | }, 117 | // SASS support 118 | { 119 | test: /\.s[a|c]ss$/, 120 | loader: extractCSS.extract({ 121 | use: [ 122 | { 123 | loader: 'css-loader', 124 | options: { url: false } 125 | }, 126 | 'sass-loader' 127 | ], 128 | fallback: 'vue-style-loader' 129 | }) 130 | 131 | }, 132 | // .vue single file component support 133 | { 134 | test: /\.vue$/, 135 | loader: 'ns-vue-loader', 136 | options: { 137 | loaders: { 138 | css: extractCSS.extract("css-loader"), 139 | scss: extractCSS.extract({ 140 | use: [ 141 | { 142 | loader: 'css-loader', 143 | options: { url: false } 144 | }, 145 | 'sass-loader' 146 | ], 147 | fallback: 'vue-style-loader' 148 | }) 149 | } 150 | } 151 | } 152 | ]; 153 | } 154 | 155 | function getPlugins(platform, env) { 156 | let plugins = [ 157 | extractMainSheet, 158 | extractCSS, 159 | 160 | new MergeFilesPlugin({ 161 | filename: 'app.css', 162 | test: /app-[0-1]\.css/, 163 | deleteSourceFiles: true 164 | }), 165 | 166 | // Vendor libs go to the vendor.js chunk 167 | new webpack.optimize.CommonsChunkPlugin({ 168 | name: ["vendor"], 169 | }), 170 | 171 | // Define useful constants like TNS_WEBPACK 172 | new webpack.DefinePlugin({ 173 | "global.TNS_WEBPACK": "true", 174 | }), 175 | 176 | // Copy assets to out dir. Add your own globs as needed. 177 | new CopyWebpackPlugin([ 178 | //{ from: mainSheet }, 179 | { from: "css/**" }, 180 | { from: "fonts/**" }, 181 | { from: "**/*.jpg" }, 182 | { from: "**/*.png" }, 183 | { from: "**/*.xml" }, 184 | ], { ignore: ["App_Resources/**"] }), 185 | 186 | // Generate a bundle starter script and activate it in package.json 187 | new nsWebpack.GenerateBundleStarterPlugin([ 188 | "./vendor", 189 | "./bundle", 190 | ]), 191 | ]; 192 | 193 | if (env.uglify) { 194 | plugins.push(new webpack.LoaderOptionsPlugin({ minimize: true })); 195 | 196 | // Work around an Android issue by setting compress = false 197 | const compress = platform !== "android"; 198 | plugins.push(new webpack.optimize.UglifyJsPlugin({ 199 | mangle: { except: nsWebpack.uglifyMangleExcludes }, 200 | compress, 201 | })); 202 | } 203 | 204 | return plugins; 205 | } 206 | 207 | // Resolve platform-specific modules like module.android.js 208 | function getExtensions(platform) { 209 | return Object.freeze([ 210 | `.${platform}.js`, 211 | ".js", 212 | `.${platform}.css`, 213 | ".css", 214 | `.${platform}.scss`, 215 | ".scss", 216 | `.${platform}.vue`, 217 | ".vue", 218 | ]); 219 | } 220 | --------------------------------------------------------------------------------