├── .circleci
└── config.yml
├── .gitignore
├── LICENSE
├── README.md
├── deploy-docs.sh
├── docs
├── README.md
├── SUMMARY.md
├── babel.md
├── backend.md
├── commands.md
├── e2e.md
├── env.md
├── linter.md
├── pre-processors.md
├── prerender.md
├── proxy.md
├── static.md
├── structure.md
└── unit.md
├── lib
├── clone.js
├── de-indent.js
└── metalsmith-copy.js
├── meta.js
├── metalsmith.js
├── package-lock.json
├── package.json
├── scenarios
├── README.md
├── full-class.json
├── full-karma-airbnb.json
├── full-typescript-class.json
├── full-typescript.json
├── full.json
├── index.js
└── minimal.json
├── template
├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── README.md
├── build
│ ├── build.js
│ ├── build.lib.js
│ ├── check-versions.js
│ ├── logo.png
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ ├── webpack.prod.conf.js
│ ├── webpack.prod.lib.conf.js
│ └── webpack.test.conf.js
├── config
│ ├── dev.env.js
│ ├── index.js
│ ├── prod.env.js
│ └── test.env.js
├── index.html
├── package.json
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ └── HelloWorld.vue
│ ├── hooks.js
│ ├── hooks.ts
│ ├── index.lib.js
│ ├── index.lib.ts
│ ├── main.js
│ ├── main.ts
│ ├── router
│ │ ├── index.js
│ │ └── index.ts
│ └── typings.d.ts
├── static
│ └── .gitkeep
├── test
│ ├── e2e
│ │ ├── custom-assertions
│ │ │ └── elementCount.js
│ │ ├── nightwatch.conf.js
│ │ ├── runner.js
│ │ └── specs
│ │ │ └── test.js
│ └── unit
│ │ ├── .eslintrc
│ │ ├── index.js
│ │ ├── jest.conf.js
│ │ ├── karma.conf.js
│ │ ├── setup.js
│ │ ├── specs
│ │ ├── HelloWorld.spec.js
│ │ └── HelloWorld.spec.ts
│ │ └── typings.d.ts
├── tsconfig.json
└── tslint.json
└── utils
└── index.js
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | vm_settings: &vm_settings
3 | docker:
4 | - image: circleci/node:6.12.3-browsers
5 |
6 | jobs:
7 | install_template_deps:
8 | <<: *vm_settings
9 | working_directory: ~/project/webpack-template
10 | steps:
11 | - checkout
12 | - restore_cache:
13 | key: template-cache-{{ checksum "package.json" }}
14 | - run:
15 | name: Install npm dependencies
16 | command: npm install
17 | - save_cache:
18 | key: template-cache-{{ checksum "package.json" }}
19 | paths:
20 | - node_modules
21 | - run:
22 | name: Rollout minimal scenario
23 | command: VUE_TEMPL_TEST=minimal node_modules/.bin/vue init . test-minimal
24 | - run:
25 | name: Rollout full scenario
26 | command: VUE_TEMPL_TEST=full node_modules/.bin/vue init . test-full
27 | - run:
28 | name: Rollout full-karma-airbnb scenario
29 | command: VUE_TEMPL_TEST=full-karma-airbnb node_modules/.bin/vue init . test-full-karma-airbnb
30 | - run:
31 | name: Rollout full-class scenario
32 | command: VUE_TEMPL_TEST=full-class node_modules/.bin/vue init . test-full-class
33 | - run:
34 | name: Rollout full-typescript scenario
35 | command: VUE_TEMPL_TEST=full-typescript node_modules/.bin/vue init . test-full-typescript
36 | - run:
37 | name: Rollout full-typescript-class scenario
38 | command: VUE_TEMPL_TEST=full-typescript-class node_modules/.bin/vue init . test-full-typescript-class
39 | - persist_to_workspace:
40 | root: ~/project/webpack-template
41 | paths:
42 | - node_modules
43 | - test-*
44 |
45 | scenario_minimal:
46 | <<: *vm_settings
47 | environment:
48 | - VUE_TEMPL_TEST: minimal
49 | working_directory: ~/project/webpack-template/test-minimal
50 | steps:
51 | - attach_workspace:
52 | at: '~/project/webpack-template'
53 | - restore_cache:
54 | key: template-cache-minimal-{{ checksum "package.json" }}
55 | - run:
56 | name: Install npm dependencies
57 | command: npm install
58 | - save_cache:
59 | key: template-cache-minimal-{{ checksum "package.json" }}
60 | paths:
61 | - node_modules
62 | - run:
63 | name: Test build
64 | command: npm run build
65 |
66 | scenario_full:
67 | <<: *vm_settings
68 | working_directory: ~/project/webpack-template/test-full
69 | environment:
70 | - VUE_TEMPL_TEST: full
71 | steps:
72 | - attach_workspace:
73 | at: '~/project/webpack-template'
74 | - restore_cache:
75 | key: template-cache-full-{{ checksum "package.json" }}
76 | - run:
77 | name: Install npm dependencies
78 | command: npm install
79 | - save_cache:
80 | key: template-cache-full-{{ checksum "package.json" }}
81 | paths:
82 | - node_modules
83 | - run:
84 | name: Run Lint
85 | command: npm run lint -- --fix
86 | - run:
87 | name: Run Unit tests
88 | command: npm run unit
89 | when: always
90 | - run:
91 | name: Run e2e tests
92 | command: npm run e2e
93 | when: always
94 | - run:
95 | name: Test build
96 | command: npm run build
97 | when: always
98 |
99 | scenario_full-karma-airbnb:
100 | <<: *vm_settings
101 | working_directory: ~/project/webpack-template/test-full-karma-airbnb
102 | environment:
103 | - VUE_TEMPL_TEST: full-karma-airbnb
104 | steps:
105 | - attach_workspace:
106 | at: '~/project/webpack-template'
107 | - restore_cache:
108 | key: template-cache-full-karma-airbnb-{{ checksum "package.json" }}
109 | - run:
110 | name: Install npm dependencies
111 | command: npm install
112 | - save_cache:
113 | key: template-cache-full-karma-airbnb-{{ checksum "package.json" }}
114 | paths:
115 | - node_modules
116 | - run:
117 | name: Run Lint
118 | command: npm run lint -- --fix
119 | - run:
120 | name: Run Unit tests
121 | command: npm run unit
122 | when: always
123 | - run:
124 | name: Run e2e tests
125 | command: npm run e2e
126 | when: always
127 | - run:
128 | name: Test build
129 | command: npm run build
130 | when: always
131 |
132 | scenario_full_class:
133 | <<: *vm_settings
134 | working_directory: ~/project/webpack-template/test-full-class
135 | environment:
136 | - VUE_TEMPL_TEST: full-class
137 | steps:
138 | - attach_workspace:
139 | at: '~/project/webpack-template'
140 | - restore_cache:
141 | key: template-cache-full-class-{{ checksum "package.json" }}
142 | - run:
143 | name: Install npm dependencies
144 | command: npm install
145 | - save_cache:
146 | key: template-cache-full-class-{{ checksum "package.json" }}
147 | paths:
148 | - node_modules
149 | - run:
150 | name: Run Lint
151 | command: npm run lint -- --fix
152 | - run:
153 | name: Run Unit tests
154 | command: npm run unit
155 | when: always
156 | - run:
157 | name: Run e2e tests
158 | command: npm run e2e
159 | when: always
160 | - run:
161 | name: Test build
162 | command: npm run build
163 | when: always
164 |
165 | scenario_full-typescript:
166 | <<: *vm_settings
167 | working_directory: ~/project/webpack-template/test-full-typescript
168 | environment:
169 | - VUE_TEMPL_TEST: full-typescript
170 | steps:
171 | - attach_workspace:
172 | at: '~/project/webpack-template'
173 | - restore_cache:
174 | key: template-cache-full-typescript-{{ checksum "package.json" }}
175 | - run:
176 | name: Install npm dependencies
177 | command: npm install
178 | - save_cache:
179 | key: template-cache-full-typescript-{{ checksum "package.json" }}
180 | paths:
181 | - node_modules
182 | - run:
183 | name: Run Lint
184 | command: npm run lint -- --fix
185 | - run:
186 | name: Run Unit tests
187 | command: npm run unit
188 | when: always
189 | - run:
190 | name: Run e2e tests
191 | command: npm run e2e
192 | when: always
193 | - run:
194 | name: Test build
195 | command: npm run build
196 | when: always
197 |
198 | scenario_full-typescript-class:
199 | <<: *vm_settings
200 | working_directory: ~/project/webpack-template/test-full-typescript-class
201 | environment:
202 | - VUE_TEMPL_TEST: full-typescript-class
203 | steps:
204 | - attach_workspace:
205 | at: '~/project/webpack-template'
206 | - restore_cache:
207 | key: template-cache-full-typescript-class-{{ checksum "package.json" }}
208 | - run:
209 | name: Install npm dependencies
210 | command: npm install
211 | - save_cache:
212 | key: template-cache-full-typescript-class-{{ checksum "package.json" }}
213 | paths:
214 | - node_modules
215 | - run:
216 | name: Run Lint
217 | command: npm run lint -- --fix
218 | - run:
219 | name: Run Unit tests
220 | command: npm run unit
221 | when: always
222 | - run:
223 | name: Run e2e tests
224 | command: npm run e2e
225 | when: always
226 | - run:
227 | name: Test build
228 | command: npm run build
229 | when: always
230 |
231 |
232 | workflows:
233 | version: 2
234 | build_and_test:
235 | jobs:
236 | - install_template_deps
237 | - scenario_minimal:
238 | requires:
239 | - install_template_deps
240 | - scenario_full:
241 | requires:
242 | - install_template_deps
243 | - scenario_full-karma-airbnb:
244 | requires:
245 | - install_template_deps
246 | - scenario_full_class:
247 | requires:
248 | - install_template_deps
249 | - scenario_full-karma-airbnb:
250 | requires:
251 | - install_template_deps
252 | - scenario_full-typescript:
253 | requires:
254 | - install_template_deps
255 | - scenario_full-typescript-class:
256 | requires:
257 | - install_template_deps
258 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | docs/_book
4 | test/
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013-present, Yuxi (Evan) You
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
13 | all 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
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-webpack-boilerplate [](https://circleci.com/gh/Toilal/vue-webpack-template)
2 |
3 | > A full-featured Webpack setup with hot-reload, lint-on-save, unit testing & css extraction.
4 |
5 | > This template is Vue 2.0 compatible.
6 |
7 | > This is a fork of official webpack template that brings more options, like TypeScript, Library, Class-Style
8 | components ...
9 |
10 | ## Documentation
11 |
12 | - [For this template](http://toilal.github.io/vue-webpack-template): common questions specific to this template are answered and each part is described in greater detail
13 | - [For Vue 2.0](http://vuejs.org/guide/): general information about how to work with Vue, not specific to this template
14 |
15 | ## Usage
16 |
17 | This is a project template for [vue-cli](https://github.com/vuejs/vue-cli). **It is recommended to use npm 3+ for a more efficient dependency tree.**
18 |
19 | ``` bash
20 | $ npm install -g vue-cli
21 | $ vue init Toilal/vue-webpack-template my-project
22 | $ cd my-project
23 | $ npm install
24 | $ npm run dev
25 | ```
26 |
27 | This will scaffold the project using the `master` branch. If you wish to use the latest version of the webpack template, do the following instead:
28 |
29 | ``` bash
30 | $ vue init webpack#develop my-project
31 | ```
32 |
33 | :warning: **The develop branch is not considered stable and can contain bugs or not build at all, so use at your own risk.**
34 |
35 | The development server will run on port 8080 by default. If that port is already in use on your machine, the next free port will be used.
36 |
37 | ## What's Included
38 |
39 | - `npm run dev`: first-in-class development experience.
40 | - Webpack + `vue-loader` for single file Vue components.
41 | - State preserving hot-reload
42 | - State preserving compilation error overlay
43 | - Lint-on-save with ESLint
44 | - Source maps
45 |
46 | - `npm run build`: Production ready build.
47 | - JavaScript minified with [UglifyJS v3](https://github.com/mishoo/UglifyJS2/tree/harmony).
48 | - HTML minified with [html-minifier](https://github.com/kangax/html-minifier).
49 | - CSS across all components extracted into a single file and minified with [cssnano](https://github.com/ben-eb/cssnano).
50 | - Static assets compiled with version hashes for efficient long-term caching, and an auto-generated production `index.html` with proper URLs to these generated assets.
51 | - Use `npm run build --report`to build with bundle size analytics.
52 |
53 | - `npm run unit`: Unit tests run in [JSDOM](https://github.com/tmpvar/jsdom) with [Jest](https://facebook.github.io/jest/), or in PhantomJS with Karma + Mocha + karma-webpack.
54 | - Supports ES2015+ in test files.
55 | - Easy mocking.
56 |
57 | - `npm run e2e`: End-to-end tests with [Nightwatch](http://nightwatchjs.org/).
58 | - Run tests in multiple browsers in parallel.
59 | - Works with one command out of the box:
60 | - Selenium and chromedriver dependencies automatically handled.
61 | - Automatically spawns the Selenium server.
62 |
63 | ### Fork It And Make Your Own
64 |
65 | You can fork this repo to create your own boilerplate, and use it with `vue-cli`:
66 |
67 | ``` bash
68 | vue init username/repo my-project
69 | ```
70 |
--------------------------------------------------------------------------------
/deploy-docs.sh:
--------------------------------------------------------------------------------
1 | cd docs
2 | rm -rf _book
3 | gitbook build
4 | cd _book
5 | git init
6 | git add -A
7 | git commit -m 'update book'
8 | git push -f git@github.com:Toilal/vue-webpack-template.git master:gh-pages
9 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | This boilerplate is targeted towards large, serious projects and assumes you are somewhat familiar with Webpack and `vue-loader`. Make sure to also read [`vue-loader`'s documentation](https://vue-loader.vuejs.org/) for common workflow recipes.
4 |
5 | If you just want to try out `vue-loader` or whip out a quick prototype, use the [webpack-simple](https://github.com/vuejs-templates/webpack-simple) template instead.
6 |
7 | ## Quickstart
8 |
9 | To use this template, scaffold a project with [vue-cli](https://github.com/vuejs/vue-cli). **It is recommended to use npm 3+ for a more efficient dependency tree.**
10 |
11 | ``` bash
12 | $ npm install -g vue-cli
13 | $ vue init Toilal/vue-webpack-template my-project
14 | $ cd my-project
15 | $ npm install
16 | $ npm run dev
17 | ```
18 |
--------------------------------------------------------------------------------
/docs/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | - [Project Structure](structure.md)
4 | - [Build Commands](commands.md)
5 | - [Babel Configuration](babel.md)
6 | - [Linter Configuration](linter.md)
7 | - [Pre-Processors](pre-processors.md)
8 | - [Handling Static Assets](static.md)
9 | - [Environment Variables](env.md)
10 | - [Integrate with Backend Framework](backend.md)
11 | - [API Proxying During Development](proxy.md)
12 | - [Unit Testing](unit.md)
13 | - [End-to-end Testing](e2e.md)
14 | - [Prerendering for SEO](prerender.md)
15 |
--------------------------------------------------------------------------------
/docs/babel.md:
--------------------------------------------------------------------------------
1 | # Babel Configuration
2 |
3 | This boilerplate uses [`babel-preset-env`](https://www.npmjs.com/package/babel-preset-env) for configuring babel. You can read more about it here - http://2ality.com/2017/02/babel-preset-env.html.
4 |
5 | > A Babel preset that compiles ES2015+ down to ES5 by automatically determining the Babel plugins and polyfills you need based on your targeted browser or runtime environments.
6 |
7 | It uses [`browserslist`](https://github.com/ai/browserslist) to parse this information, so we can use any [valid query format supported by `browserslist`](https://github.com/ai/browserslist#queries).
8 |
9 | However there is a caveat. `browserslist` recommends defining the target in a common place like `package.json` or in a `.browserslistrc` config file. This allows tools like [`autoprefixer`](https://github.com/postcss/autoprefixer) and [`eslint-plugin-compat`](https://github.com/amilajack/eslint-plugin-compat) to share the config. For this template, `browserslist` is configured in the `package.json`:
10 |
11 | ```json
12 | {
13 | "...": "...",
14 | "browserslist": [
15 | "> 1%",
16 | "last 2 versions",
17 | "not ie <= 8"
18 | ]
19 | }
20 | ```
21 |
22 | But the latest stable release of `babel-preset-env`, `v1.6.1` does not support loading the config from `package.json`. So the target environment is repeated in `.babelrc`. If you wish to change your target environment, please be sure to update both `package.json` and `.babelrc`. Note that this has been fixed in the beta version([`@babel/preset-env@7.0.0-beta.34`](https://github.com/babel/babel/tree/master/packages/babel-preset-env)) and the template will be updated once it is out of beta.
23 |
--------------------------------------------------------------------------------
/docs/backend.md:
--------------------------------------------------------------------------------
1 | # Integrating with Backend Framework
2 |
3 | If you are building a purely-static app (one that is deployed separately from the backend API), then you probably don't even need to edit `config/index.js`. However, if you want to integrate this template with an existing backend framework, e.g. Rails/Django/Laravel, which comes with their own project structures, you can edit `config/index.js` to directly generate front-end assets into your backend project.
4 |
5 | Let's take a look at the default `config/index.js`:
6 |
7 | ``` js
8 | // config/index.js
9 | 'use strict'
10 | const path = require('path')
11 |
12 | module.exports = {
13 | dev: {
14 | / Paths
15 | assetsSubDirectory: 'static',
16 | assetsPublicPath: '/',
17 | proxyTable: {},
18 |
19 | // Various Dev Server settings
20 | host: 'localhost',
21 | port: 8080,
22 |
23 | // skipping other options as they are only convenience features
24 | },
25 | build: {
26 | // Template for index.html
27 | index: path.resolve(__dirname, '../dist/index.html'),
28 |
29 | // Paths
30 | assetsRoot: path.resolve(__dirname, '../dist'),
31 | assetsSubDirectory: 'static',
32 | assetsPublicPath: '/',
33 |
34 | productionSourceMap: true,
35 |
36 | // skipping the rest ...
37 | },
38 | }
39 | ```
40 |
41 | Inside the `build` section, we have the following options:
42 |
43 | ### `build.index`
44 |
45 | > Must be an absolute path on your local file system.
46 |
47 | This is where the `index.html` (with injected asset URLs) will be generated.
48 |
49 | If you are using this template with a backend-framework, you can edit `index.html` accordingly and point this path to a view file rendered by your backend app, e.g. `app/views/layouts/application.html.erb` for a Rails app, or `resources/views/index.blade.php` for a Laravel app.
50 |
51 | ### `build.assetsRoot`
52 |
53 | > Must be an absolute path on your local file system.
54 |
55 | This should point to the root directory that contains all the static assets for your app. For example, `public/` for both Rails/Laravel.
56 |
57 | ### `build.assetsSubDirectory`
58 |
59 | Nest webpack-generated assets under this directory in `build.assetsRoot`, so that they are not mixed with other files you may have in `build.assetsRoot`. For example, if `build.assetsRoot` is `/path/to/dist`, and `build.assetsSubDirectory` is `static`, then all Webpack assets will be generated in `path/to/dist/static`.
60 |
61 | This directory will be cleaned before each build, so it should only contain assets generated by the build.
62 |
63 | Files inside `static/` will be copied into this directory as-is during build. This means if you change this prefix, all your absolute URLs referencing files in `static/` will also need to be changed. See [Handling Static Assets](static.md) for more details.
64 |
65 | ### `build.assetsPublicPath`
66 |
67 | This should be the URL path where your `build.assetsRoot` will be served from over HTTP. In most cases, this will be root (`/`). Only change this if your backend framework serves static assets with a path prefix. Internally, this is passed to Webpack as `output.publicPath`.
68 |
69 | ### `build.productionSourceMap`
70 |
71 | Whether to generate source maps for production build.
72 |
73 | ### `dev.port`
74 |
75 | Specify the port for the dev server to listen to.
76 |
77 | ### `dev.proxyTable`
78 |
79 | Define proxy rules for the dev server. See [API Proxying During Development](proxy.md) for more details.
80 |
--------------------------------------------------------------------------------
/docs/commands.md:
--------------------------------------------------------------------------------
1 | # Build Commands
2 |
3 | All build commands are executed via [NPM Scripts](https://docs.npmjs.com/misc/scripts).
4 |
5 | ### `npm run dev`
6 |
7 | > Starts a Node.js local development server. See [API Proxying During Development](proxy.md) for more details.
8 |
9 | - Webpack + `vue-loader` for single file Vue components.
10 | - State preserving hot-reload
11 | - State preserving compilation error overlay
12 | - Lint-on-save with ESLint
13 | - Source maps
14 |
15 | ### `npm run build`
16 |
17 | > Build assets for production. See [Integrating with Backend Framework](backend.md) for more details.
18 |
19 | - JavaScript minified with [UglifyJS v3](https://github.com/mishoo/UglifyJS2/tree/harmony).
20 | - HTML minified with [html-minifier](https://github.com/kangax/html-minifier).
21 | - CSS across all components extracted into a single file and minified with [cssnano](https://github.com/ben-eb/cssnano).
22 | - All static assets compiled with version hashes for efficient long-term caching, and a production `index.html` is auto-generated with proper URLs to these generated assets.
23 |
24 | ### `npm run unit`
25 |
26 | > Run unit tests in JSDOM with [Jest](https://facebook.github.io/jest/docs/getting-started.html). See [Unit Testing](unit.md) for more details.
27 |
28 | - Supports ES2015+ in test files.
29 | - Easy [mocking](https://facebook.github.io/jest/docs/mock-functions.html).
30 |
31 | ### `npm run e2e`
32 |
33 | > Run end-to-end tests with [Nightwatch](http://nightwatchjs.org/). See [End-to-end Testing](e2e.md) for more details.
34 |
35 | - Run tests in multiple browsers in parallel.
36 | - Works with one command out of the box:
37 | - Selenium and chromedriver dependencies automatically handled.
38 | - Automatically spawns the Selenium server.
39 |
40 | ### `npm run lint`
41 |
42 | > Runs eslint and reports any linting errors in your code. See [Linter Configuration](linter.md)
43 |
--------------------------------------------------------------------------------
/docs/e2e.md:
--------------------------------------------------------------------------------
1 | # End-to-end Testing
2 |
3 | This boilerplate uses [Nightwatch.js](http://nightwatchjs.org) for e2e tests. Nightwatch.js is a highly integrated e2e test runner built on top of Selenium. This boilerplate comes with Selenium server and chromedriver binaries pre-configured for you, so you don't have to mess with these yourself.
4 |
5 | Let's take a look at the files in the `test/e2e` directory:
6 |
7 | - `runner.js`
8 |
9 | A Node.js script that starts the dev server, and then launches Nightwatch to run tests against it. This is the script that will run when you run `npm run e2e`.
10 |
11 | - `nightwatch.conf.js`
12 |
13 | Nightwatch configuration file. See [Nightwatch's docs on configuration](http://nightwatchjs.org/gettingstarted#settings-file) for more details.
14 |
15 | - `custom-assertions/`
16 |
17 | Custom assertions that can be used in Nightwatch tests. See [Nightwatch's docs on writing custom assertions](http://nightwatchjs.org/guide#writing-custom-assertions) for more details.
18 |
19 | - `specs/`
20 |
21 | Your actual tests! See [Nightwatch's docs on writing tests](http://nightwatchjs.org/guide#writing-tests) and [API reference](http://nightwatchjs.org/api) for more details.
22 |
23 | ### Running Tests in More Browsers
24 |
25 | To configure which browsers to run the tests in, add an entry under "test_settings" in [`test/e2e/nightwatch.conf.js`](https://github.com/vuejs-templates/webpack/blob/master/template/test/e2e/nightwatch.conf.js#L17-L39) , and also the `--env` flag in [`test/e2e/runner.js`](https://github.com/vuejs-templates/webpack/blob/master/template/test/e2e/runner.js#L15). If you wish to configure remote testing on services like SauceLabs, you can either make the Nightwatch config conditional based on environment variables, or use a separate config file altogether. Consult [Nightwatch's docs on Selenium](http://nightwatchjs.org/guide#selenium-settings) for more details.
26 |
--------------------------------------------------------------------------------
/docs/env.md:
--------------------------------------------------------------------------------
1 | # Environment Variables
2 |
3 | Sometimes it is practical to have different config values according to the environment that the application is running in.
4 |
5 | As an example:
6 |
7 | ```js
8 | // config/prod.env.js
9 | module.exports = {
10 | NODE_ENV: '"production"',
11 | DEBUG_MODE: false,
12 | API_KEY: '"..."' // this is shared between all environments
13 | }
14 |
15 | // config/dev.env.js
16 | module.exports = merge(prodEnv, {
17 | NODE_ENV: '"development"',
18 | DEBUG_MODE: true // this overrides the DEBUG_MODE value of prod.env
19 | })
20 |
21 | // config/test.env.js
22 | module.exports = merge(devEnv, {
23 | NODE_ENV: '"testing"'
24 | })
25 | ```
26 |
27 | > **Note:** string variables need to be wrapped into single and double quotes `'"..."'`
28 |
29 | So, the environment variables are:
30 | - Production
31 | - NODE_ENV = 'production',
32 | - DEBUG_MODE = false,
33 | - API_KEY = '...'
34 | - Development
35 | - NODE_ENV = 'development',
36 | - DEBUG_MODE = true,
37 | - API_KEY = '...'
38 | - Testing
39 | - NODE_ENV = 'testing',
40 | - DEBUG_MODE = true,
41 | - API_KEY = '...'
42 |
43 | As we can see, `test.env` inherits the `dev.env` and the `dev.env` inherits the `prod.env`.
44 |
45 | ### Usage
46 |
47 | It is simple to use the environment variables in your code. For example:
48 |
49 | ```js
50 | Vue.config.productionTip = process.env.NODE_ENV === 'production'
51 | ```
52 |
--------------------------------------------------------------------------------
/docs/linter.md:
--------------------------------------------------------------------------------
1 | # Linter Configuration
2 |
3 | This boilerplate uses [ESLint](https://eslint.org/) as the linter, and uses the [Standard](https://github.com/feross/standard/blob/master/RULES.md) preset with some small customizations.
4 |
5 | ## eslint-plugin-vue
6 |
7 | We always add [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) as well, which comes with a whole bunch of helpful rules to write consistent Vue components - it can also lint templates!
8 |
9 | You can find an overview of all the available rules on [github](https://github.com/vuejs/eslint-plugin-vue#gear-configs). We chose to add the `essential` configs, but we recommend to switch to the bigger `strongly-recommended` or `recommended` rulesets once you are familiar with them.
10 |
11 | ## Customizing
12 |
13 | If you are not happy with the default linting rules, you have several options:
14 |
15 | 1. Overwrite individual rules in `.eslintrc.js`. For example, you can add the following rule to enforce semicolons instead of omitting them:
16 |
17 | ``` js
18 | // .eslintrc.js
19 | "semi": [2, "always"]
20 | ```
21 |
22 | 2. Pick a different ESLint preset when generating the project, for example [eslint-config-airbnb](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb).
23 |
24 | 3. Pick "none" for ESLint preset when generating the project and define your own rules. See [ESLint documentation](https://eslint.org/docs/rules/) for more details.
25 |
26 | ## Fixing Linting Errors
27 |
28 | You can run the following command to let eslint fix any errors it finds (if it can - not all errors are fixable like this):
29 |
30 | ```
31 | npm run lint -- --fix
32 | ```
33 |
34 | *(The `--` in the middle is necessary to ensure the `--fix` option is passdd to `eslint`, not to `npm`. It can be omitted whne using yarn)*
35 |
36 |
--------------------------------------------------------------------------------
/docs/pre-processors.md:
--------------------------------------------------------------------------------
1 | # Pre-Processors
2 |
3 | This boilerplate has pre-configured CSS extraction for most popular CSS pre-processors including LESS, SASS, Stylus, and PostCSS. To use a pre-processor, all you need to do is install the appropriate webpack loader for it. For example, to use SASS:
4 |
5 | ``` bash
6 | npm install sass-loader node-sass --save-dev
7 | ```
8 |
9 | Note you also need to install `node-sass` because `sass-loader` depends on it as a peer dependency.
10 |
11 | ### Using Pre-Processors inside Components
12 |
13 | Once installed, you can use the pre-processors inside your `*.vue` components using the `lang` attribute on `
19 | ```
20 |
21 | ### A note on SASS syntax
22 |
23 | - `lang="scss"` corresponds to the CSS-superset syntax (with curly braces and semicolons).
24 | - `lang="sass"` corresponds to the indentation-based syntax.
25 |
26 | ### PostCSS
27 |
28 | Styles in `*.vue` files and style files (`*.css`, `*.scss` etc) are piped through PostCSS by default, so you don't need to use a specific loader for it.
29 |
30 | You can simply add PostCSS plugins you want to use to the `.postcssrc.js`file in your project's root directory:
31 |
32 | ``` js
33 | // https://github.com/michael-ciniawsky/postcss-load-config
34 |
35 | module.exports = {
36 | "plugins": {
37 | // to edit target browsers: use "browserslist" field in package.json
38 | "postcss-import": {},
39 | "autoprefixer": {}
40 | }
41 | }
42 | ```
43 |
44 | See [vue-loader's related documentation](http://vuejs.github.io/vue-loader/en/features/postcss.html) for more details.
45 |
46 | ### Standalone CSS Files
47 |
48 | To ensure consistent extraction and processing, it is recommended to import global, standalone style files from your root `App.vue` component, for example:
49 |
50 | ``` html
51 |
52 |
53 | ```
54 |
55 | Note you should probably only do this for the styles written by yourself for your application. For existing libraries e.g. Bootstrap or Semantic UI, you can place them inside `/static` and reference them directly in `index.html`. This avoids extra build time and also is better for browser caching. (See [Static Asset Handling](static.md))
56 |
--------------------------------------------------------------------------------
/docs/prerender.md:
--------------------------------------------------------------------------------
1 | # Prerendering for SEO
2 |
3 | If you want to prerender routes that will not significantly change once pushed to production, use this Webpack plugin: [prerender-spa-plugin](https://www.npmjs.com/package/prerender-spa-plugin), which has been tested for use with Vue. For pages that _do_ frequently change, [Prerender.io](https://prerender.io/) and [Netlify](https://www.netlify.com/pricing) both offer plans for regularly re-prerendering your content for search engines.
4 |
5 | ## Using `prerender-spa-plugin`
6 |
7 | 1. Install it as a dev dependency:
8 |
9 | ```bash
10 | npm install --save-dev prerender-spa-plugin
11 | ```
12 |
13 | 2. Require it in **build/webpack.prod.conf.js**:
14 |
15 | ```js
16 | // This line should go at the top of the file where other 'imports' live in
17 | const PrerenderSpaPlugin = require('prerender-spa-plugin')
18 | ```
19 |
20 | 3. Configure it in the `plugins` array (also in **build/webpack.prod.conf.js**):
21 |
22 | ```js
23 | new PrerenderSpaPlugin(
24 | // Path to compiled app
25 | path.join(__dirname, '../dist'),
26 | // List of endpoints you wish to prerender
27 | [ '/' ]
28 | )
29 | ```
30 |
31 | If you also wanted to prerender `/about` and `/contact`, then that array would be `[ '/', '/about', '/contact' ]`.
32 |
33 | 4. Enable history mode for `vue-router`:
34 | ```js
35 | const router = new VueRouter({
36 | mode: 'history',
37 | routes: [...]
38 | })
39 | ```
40 |
--------------------------------------------------------------------------------
/docs/proxy.md:
--------------------------------------------------------------------------------
1 | # API Proxying During Development
2 |
3 | When integrating this boilerplate with an existing backend, a common need is to access the backend API when using the dev server. To achieve that, we can run the dev server and the API backend side-by-side (or remotely), and let the dev server proxy all API requests to the actual backend.
4 |
5 | To configure the proxy rules, edit `dev.proxyTable` option in `config/index.js`. The dev server is using [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) for proxying, so you should refer to its docs for detailed usage. But here's a simple example:
6 |
7 | ``` js
8 | // config/index.js
9 | module.exports = {
10 | // ...
11 | dev: {
12 | proxyTable: {
13 | // proxy all requests starting with /api to jsonplaceholder
14 | '/api': {
15 | target: 'http://jsonplaceholder.typicode.com',
16 | changeOrigin: true,
17 | pathRewrite: {
18 | '^/api': ''
19 | }
20 | }
21 | }
22 | }
23 | }
24 | ```
25 |
26 | The above example will proxy the request `/api/posts/1` to `http://jsonplaceholder.typicode.com/posts/1`.
27 |
28 | ## URL Matching
29 |
30 | In addition to static urls you can also use glob patterns to match URLs, e.g. `/api/**`. See [Context Matching](https://github.com/chimurai/http-proxy-middleware#context-matching) for more details. In addition, you can provide a `filter` option that can be a custom function to determine whether a request should be proxied:
31 |
32 | ``` js
33 | proxyTable: {
34 | '**': {
35 | target: 'http://jsonplaceholder.typicode.com',
36 | filter: function (pathname, req) {
37 | return pathname.match('^/api') && req.method === 'GET'
38 | }
39 | }
40 | }
41 | ```
42 |
--------------------------------------------------------------------------------
/docs/static.md:
--------------------------------------------------------------------------------
1 | # Handling Static Assets
2 |
3 | You will notice in the project structure we have two directories for static assets: `src/assets` and `static/`. What is the difference between them?
4 |
5 | ### Webpacked Assets
6 |
7 | To answer this question, we first need to understand how Webpack deals with static assets. In `*.vue` components, all your templates and CSS are parsed by `vue-html-loader` and `css-loader` to look for asset URLs. For example, in `
` and `background: url(./logo.png)`, `"./logo.png"` is a relative asset path and will be **resolved by Webpack as a module dependency**.
8 |
9 | Because `logo.png` is not JavaScript, when treated as a module dependency, we need to use `url-loader` and `file-loader` to process it. This template has already configured these loaders for you, so you get features such as filename fingerprinting and conditional base64 inlining for free, while being able to use relative/module paths without worrying about deployment.
10 |
11 | Since these assets may be inlined/copied/renamed during build, they are essentially part of your source code. This is why it is recommended to place Webpack-processed static assets inside `/src`, alongside other source files. In fact, you don't even have to put them all in `/src/assets`: you can organize them based on the module/component using them. For example, you can put each component in its own directory, with its static assets right next to it.
12 |
13 | ### Asset Resolving Rules
14 |
15 | - **Relative URLs**, e.g. `./assets/logo.png` will be interpreted as a module dependency. They will be replaced with an auto-generated URL based on your Webpack output configuration.
16 |
17 | - **Non-prefixed URLs**, e.g. `assets/logo.png` will be treated the same as the relative URLs and translated into `./assets/logo.png`.
18 |
19 | - **URLs prefixed with `~`** are treated as a module request, similar to `require('some-module/image.png')`. You need to use this prefix if you want to leverage Webpack's module resolving configurations. For example if you have a resolve alias for `assets`, you need to use `
` to ensure that alias is respected.
20 |
21 | - **Root-relative URLs**, e.g. `/assets/logo.png` are not processed at all.
22 |
23 | ### Getting Asset Paths in JavaScript
24 |
25 | In order for Webpack to return the correct asset paths, you need to use `require('./relative/path/to/file.jpg')`, which will get processed by `file-loader` and returns the resolved URL. For example:
26 |
27 | ``` js
28 | computed: {
29 | background () {
30 | return require('./bgs/' + this.id + '.jpg')
31 | }
32 | }
33 | ```
34 |
35 | **Note the above example will include every image under `./bgs/` in the final build.** This is because Webpack cannot guess which of them will be used at runtime, so it includes them all.
36 |
37 | ### "Real" Static Assets
38 |
39 | In comparison, files in `static/` are not processed by Webpack at all: they are directly copied to their final destination as-is, with the same filename. You must reference these files using absolute paths, which is determined by joining `build.assetsPublicPath` and `build.assetsSubDirectory` in `config.js`.
40 |
41 | As an example, with the following default values:
42 |
43 | ``` js
44 | // config/index.js
45 | module.exports = {
46 | // ...
47 | build: {
48 | assetsPublicPath: '/',
49 | assetsSubDirectory: 'static'
50 | }
51 | }
52 | ```
53 |
54 | Any file placed in `static/` should be referenced using the absolute URL `/static/[filename]`. If you change `assetSubDirectory` to `assets`, then these URLs will need to be changed to `/assets/[filename]`.
55 |
56 | We will learn more about the config file in the section about [backend integration](backend.md).
57 |
--------------------------------------------------------------------------------
/docs/structure.md:
--------------------------------------------------------------------------------
1 | # Project Structure
2 |
3 | ``` bash
4 | .
5 | ├── build/ # webpack config files
6 | │ └── ...
7 | ├── config/
8 | │ ├── index.js # main project config
9 | │ └── ...
10 | ├── src/
11 | │ ├── main.js # app entry file
12 | │ ├── App.vue # main app component
13 | │ ├── components/ # ui components
14 | │ │ └── ...
15 | │ └── assets/ # module assets (processed by webpack)
16 | │ └── ...
17 | ├── static/ # pure static assets (directly copied)
18 | ├── test/
19 | │ └── unit/ # unit tests
20 | │ │ ├── specs/ # test spec files
21 | │ │ ├── eslintrc # config file for eslint with extra settings only for unit tests
22 | │ │ ├── index.js # test build entry file
23 | │ │ ├── jest.conf.js # Config file when using Jest for unit tests
24 | │ │ └── karma.conf.js # test runner config file when using Karma for unit tests
25 | │ │ ├── setup.js # file that runs before Jest runs your unit tests
26 | │ └── e2e/ # e2e tests
27 | │ │ ├── specs/ # test spec files
28 | │ │ ├── custom-assertions/ # custom assertions for e2e tests
29 | │ │ ├── runner.js # test runner script
30 | │ │ └── nightwatch.conf.js # test runner config file
31 | ├── .babelrc # babel config
32 | ├── .editorconfig # indentation, spaces/tabs and similar settings for your editor
33 | ├── .eslintrc.js # eslint config
34 | ├── .eslintignore # eslint ignore rules
35 | ├── .gitignore # sensible defaults for gitignore
36 | ├── .postcssrc.js # postcss config
37 | ├── index.html # index.html template
38 | ├── package.json # build scripts and dependencies
39 | └── README.md # Default README file
40 | ```
41 |
42 | ### `build/`
43 |
44 | This directory holds the actual configurations for both the development server and the production webpack build. Normally you don't need to touch these files unless you want to customize Webpack loaders, in which case you should probably look at `build/webpack.base.conf.js`.
45 |
46 | ### `config/index.js`
47 |
48 | This is the main configuration file that exposes some of the most common configuration options for the build setup. See [API Proxying During Development](proxy.md) and [Integrating with Backend Framework](backend.md) for more details.
49 |
50 | ### `src/`
51 |
52 | This is where most of your application code will live in. How to structure everything inside this directory is largely up to you; if you are using Vuex, you can consult the [recommendations for Vuex applications](http://vuex.vuejs.org/en/structure.html).
53 |
54 | ### `static/`
55 |
56 | This directory is an escape hatch for static assets that you do not want to process with Webpack. They will be directly copied into the same directory where webpack-built assets are generated.
57 |
58 | See [Handling Static Assets](static.md) for more details.
59 |
60 | ### `test/unit`
61 |
62 | Contains unit test related files. See [Unit Testing](unit.md) for more details.
63 |
64 | ### `test/e2e`
65 |
66 | Contains e2e test related files. See [End-to-end Testing](e2e.md) for more details.
67 |
68 | ### `index.html`
69 |
70 | This is the **template** `index.html` for our single page application. During development and builds, Webpack will generate assets, and the URLs for those generated assets will be automatically injected into this template to render the final HTML.
71 |
72 | ### `package.json`
73 |
74 | The NPM package meta file that contains all the build dependencies and [build commands](commands.md).
75 |
--------------------------------------------------------------------------------
/docs/unit.md:
--------------------------------------------------------------------------------
1 | # Unit Testing
2 |
3 | This project offers two options for unit testing:
4 |
5 | 1. Jest
6 | 2. Karma and Mocha.
7 |
8 |
9 | ## Jest
10 |
11 | - [Jest](https://facebook.github.io/jest/): the test runner that launches JSDOM runs the tests and reports the results to us.
12 |
13 | ### Files
14 |
15 | - `setup.js`
16 |
17 | Jest runs this file before it runs the unit tests. It sets the Vue production tip to false.
18 |
19 | ### Mocking Dependencies
20 |
21 | The Jest boilerplate comes with the ability to mock dependencies. See the [mock functions guide](https://facebook.github.io/jest/docs/mock-functions.html) for more details.
22 |
23 | ## Karma and Mocha
24 |
25 | - [Karma](https://karma-runner.github.io/): the test runner that launches browsers, runs the tests and reports the results to us.
26 | - [karma-webpack](https://github.com/webpack/karma-webpack): the plugin for Karma that bundles our tests using Webpack.
27 | - [Mocha](https://mochajs.org/): the test framework that we write test specs with.
28 | - [Chai](http://chaijs.com/): test assertion library that provides better assertion syntax.
29 | - [Sinon](http://sinonjs.org/): test utility library that provides spies, stubs and mocks.
30 |
31 | Chai and Sinon are integrated using [karma-sinon-chai](https://github.com/kmees/karma-sinon-chai), so all Chai interfaces (`should`, `expect`, `assert`) and `sinon` are globally available in test files.
32 |
33 | ### Files
34 |
35 | - `index.js`
36 |
37 | This is the entry file used by `karma-webpack` to bundle all the test code and source code (for coverage purposes). You can ignore it for the most part.
38 |
39 | - `specs/`
40 |
41 | This directory is where you write your actual tests. You can use full ES2015+ and all supported Webpack loaders in your tests.
42 |
43 | - `karma.conf.js`
44 |
45 | This is the Karma configuration file. See [Karma docs](https://karma-runner.github.io/) for more details.
46 |
47 | ### Running Tests in More Browsers
48 |
49 | You can run the tests in multiple real browsers by installing more [karma launchers](https://karma-runner.github.io/1.0/config/browsers.html) and adjusting the `browsers` field in `test/unit/karma.conf.js`.
50 |
51 | ### Mocking Dependencies
52 |
53 | The Karma unit test boilerplate comes with [inject-loader](https://github.com/plasticine/inject-loader) installed by default. For usage with `*.vue` components, see [vue-loader docs on testing with mocks](http://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html).
54 |
--------------------------------------------------------------------------------
/lib/clone.js:
--------------------------------------------------------------------------------
1 | /*
2 | Clone NPM module.
3 |
4 | https://www.npmjs.com/package/clone (2.1.1)
5 |
6 | Copyright © 2011-2015 Paul Vorbach
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy of
9 | this software and associated documentation files (the “Software”), to deal in
10 | the Software without restriction, including without limitation the rights to
11 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12 | the Software, and to permit persons to whom the Software is furnished to do so,
13 | subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in all
16 | copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OUT OF OR IN CONNECTION WITH THE
23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | */
25 |
26 | var clone = (function() {
27 | 'use strict';
28 |
29 | function _instanceof(obj, type) {
30 | return type != null && obj instanceof type;
31 | }
32 |
33 | var nativeMap;
34 | try {
35 | nativeMap = Map;
36 | } catch(_) {
37 | // maybe a reference error because no `Map`. Give it a dummy value that no
38 | // value will ever be an instanceof.
39 | nativeMap = function() {};
40 | }
41 |
42 | var nativeSet;
43 | try {
44 | nativeSet = Set;
45 | } catch(_) {
46 | nativeSet = function() {};
47 | }
48 |
49 | var nativePromise;
50 | try {
51 | nativePromise = Promise;
52 | } catch(_) {
53 | nativePromise = function() {};
54 | }
55 |
56 | /**
57 | * Clones (copies) an Object using deep copying.
58 | *
59 | * This function supports circular references by default, but if you are certain
60 | * there are no circular references in your object, you can save some CPU time
61 | * by calling clone(obj, false).
62 | *
63 | * Caution: if `circular` is false and `parent` contains circular references,
64 | * your program may enter an infinite loop and crash.
65 | *
66 | * @param `parent` - the object to be cloned
67 | * @param `circular` - set to true if the object to be cloned may contain
68 | * circular references. (optional - true by default)
69 | * @param `depth` - set to a number if the object is only to be cloned to
70 | * a particular depth. (optional - defaults to Infinity)
71 | * @param `prototype` - sets the prototype to be used when cloning an object.
72 | * (optional - defaults to parent prototype).
73 | * @param `includeNonEnumerable` - set to true if the non-enumerable properties
74 | * should be cloned as well. Non-enumerable properties on the prototype
75 | * chain will be ignored. (optional - false by default)
76 | */
77 | function clone(parent, circular, depth, prototype, includeNonEnumerable) {
78 | if (typeof circular === 'object') {
79 | depth = circular.depth;
80 | prototype = circular.prototype;
81 | includeNonEnumerable = circular.includeNonEnumerable;
82 | circular = circular.circular;
83 | }
84 | // maintain two arrays for circular references, where corresponding parents
85 | // and children have the same index
86 | var allParents = [];
87 | var allChildren = [];
88 |
89 | var useBuffer = typeof Buffer != 'undefined';
90 |
91 | if (typeof circular == 'undefined')
92 | circular = true;
93 |
94 | if (typeof depth == 'undefined')
95 | depth = Infinity;
96 |
97 | // recurse this function so we don't reset allParents and allChildren
98 | function _clone(parent, depth) {
99 | // cloning null always returns null
100 | if (parent === null)
101 | return null;
102 |
103 | if (depth === 0)
104 | return parent;
105 |
106 | var child;
107 | var proto;
108 | if (typeof parent != 'object') {
109 | return parent;
110 | }
111 |
112 | if (_instanceof(parent, nativeMap)) {
113 | child = new nativeMap();
114 | } else if (_instanceof(parent, nativeSet)) {
115 | child = new nativeSet();
116 | } else if (_instanceof(parent, nativePromise)) {
117 | child = new nativePromise(function (resolve, reject) {
118 | parent.then(function(value) {
119 | resolve(_clone(value, depth - 1));
120 | }, function(err) {
121 | reject(_clone(err, depth - 1));
122 | });
123 | });
124 | } else if (clone.__isArray(parent)) {
125 | child = [];
126 | } else if (clone.__isRegExp(parent)) {
127 | child = new RegExp(parent.source, __getRegExpFlags(parent));
128 | if (parent.lastIndex) child.lastIndex = parent.lastIndex;
129 | } else if (clone.__isDate(parent)) {
130 | child = new Date(parent.getTime());
131 | } else if (useBuffer && Buffer.isBuffer(parent)) {
132 | child = new Buffer(parent.length);
133 | parent.copy(child);
134 | return child;
135 | } else if (_instanceof(parent, Error)) {
136 | child = Object.create(parent);
137 | } else {
138 | if (typeof prototype == 'undefined') {
139 | proto = Object.getPrototypeOf(parent);
140 | child = Object.create(proto);
141 | }
142 | else {
143 | child = Object.create(prototype);
144 | proto = prototype;
145 | }
146 | }
147 |
148 | if (circular) {
149 | var index = allParents.indexOf(parent);
150 |
151 | if (index != -1) {
152 | return allChildren[index];
153 | }
154 | allParents.push(parent);
155 | allChildren.push(child);
156 | }
157 |
158 | if (_instanceof(parent, nativeMap)) {
159 | parent.forEach(function(value, key) {
160 | var keyChild = _clone(key, depth - 1);
161 | var valueChild = _clone(value, depth - 1);
162 | child.set(keyChild, valueChild);
163 | });
164 | }
165 | if (_instanceof(parent, nativeSet)) {
166 | parent.forEach(function(value) {
167 | var entryChild = _clone(value, depth - 1);
168 | child.add(entryChild);
169 | });
170 | }
171 |
172 | for (var i in parent) {
173 | var attrs;
174 | if (proto) {
175 | attrs = Object.getOwnPropertyDescriptor(proto, i);
176 | }
177 |
178 | if (attrs && attrs.set == null) {
179 | continue;
180 | }
181 | child[i] = _clone(parent[i], depth - 1);
182 | }
183 |
184 | if (Object.getOwnPropertySymbols) {
185 | var symbols = Object.getOwnPropertySymbols(parent);
186 | for (var i = 0; i < symbols.length; i++) {
187 | // Don't need to worry about cloning a symbol because it is a primitive,
188 | // like a number or string.
189 | var symbol = symbols[i];
190 | var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
191 | if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
192 | continue;
193 | }
194 | child[symbol] = _clone(parent[symbol], depth - 1);
195 | if (!descriptor.enumerable) {
196 | Object.defineProperty(child, symbol, {
197 | enumerable: false
198 | });
199 | }
200 | }
201 | }
202 |
203 | if (includeNonEnumerable) {
204 | var allPropertyNames = Object.getOwnPropertyNames(parent);
205 | for (var i = 0; i < allPropertyNames.length; i++) {
206 | var propertyName = allPropertyNames[i];
207 | var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
208 | if (descriptor && descriptor.enumerable) {
209 | continue;
210 | }
211 | child[propertyName] = _clone(parent[propertyName], depth - 1);
212 | Object.defineProperty(child, propertyName, {
213 | enumerable: false
214 | });
215 | }
216 | }
217 |
218 | return child;
219 | }
220 |
221 | return _clone(parent, depth);
222 | }
223 |
224 | /**
225 | * Simple flat clone using prototype, accepts only objects, usefull for property
226 | * override on FLAT configuration object (no nested props).
227 | *
228 | * USE WITH CAUTION! This may not behave as you wish if you do not know how this
229 | * works.
230 | */
231 | clone.clonePrototype = function clonePrototype(parent) {
232 | if (parent === null)
233 | return null;
234 |
235 | var c = function () {};
236 | c.prototype = parent;
237 | return new c();
238 | };
239 |
240 | // private utility functions
241 |
242 | function __objToStr(o) {
243 | return Object.prototype.toString.call(o);
244 | }
245 | clone.__objToStr = __objToStr;
246 |
247 | function __isDate(o) {
248 | return typeof o === 'object' && __objToStr(o) === '[object Date]';
249 | }
250 | clone.__isDate = __isDate;
251 |
252 | function __isArray(o) {
253 | return typeof o === 'object' && __objToStr(o) === '[object Array]';
254 | }
255 | clone.__isArray = __isArray;
256 |
257 | function __isRegExp(o) {
258 | return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
259 | }
260 | clone.__isRegExp = __isRegExp;
261 |
262 | function __getRegExpFlags(re) {
263 | var flags = '';
264 | if (re.global) flags += 'g';
265 | if (re.ignoreCase) flags += 'i';
266 | if (re.multiline) flags += 'm';
267 | return flags;
268 | }
269 | clone.__getRegExpFlags = __getRegExpFlags;
270 |
271 | return clone;
272 | })();
273 |
274 | if (typeof module === 'object' && module.exports) {
275 | module.exports = clone;
276 | }
--------------------------------------------------------------------------------
/lib/de-indent.js:
--------------------------------------------------------------------------------
1 | // de-indent from https://github.com/yyx990803/de-indent
2 |
3 | var splitRE = /\r?\n/g
4 | var emptyRE = /^\s*$/
5 | var needFixRE = /^(\r?\n)*[\t\s]/
6 |
7 | module.exports = function deindent (str) {
8 | if (!needFixRE.test(str)) {
9 | return str
10 | }
11 | var lines = str.split(splitRE)
12 | var min = Infinity
13 | var type, cur, c
14 | for (var i = 0; i < lines.length; i++) {
15 | var line = lines[i]
16 | if (!emptyRE.test(line)) {
17 | if (!type) {
18 | c = line.charAt(0)
19 | if (c === ' ' || c === '\t') {
20 | type = c
21 | cur = count(line, type)
22 | if (cur < min) {
23 | min = cur
24 | }
25 | } else {
26 | return str
27 | }
28 | } else {
29 | cur = count(line, type)
30 | if (cur < min) {
31 | min = cur
32 | }
33 | }
34 | }
35 | }
36 | return lines.map(function (line) {
37 | return line.slice(min)
38 | }).join('\n')
39 | }
40 |
41 | function count (line, type) {
42 | var i = 0
43 | while (line.charAt(i) === type) {
44 | i++
45 | }
46 | return i
47 | }
--------------------------------------------------------------------------------
/lib/metalsmith-copy.js:
--------------------------------------------------------------------------------
1 | /*
2 | Fork from https://github.com/mattwidmann/metalsmith-copy with no dependency
3 |
4 | The MIT License (MIT)
5 |
6 | Copyright (c) 2014 Matt Widmann
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 | */
26 |
27 | var debug = console.debug ? console.debug : console.log,
28 | path = require('path'),
29 | cloneDeep = require('./clone');
30 |
31 | module.exports = plugin;
32 |
33 | function plugin(options) {
34 | return function(files, metalsmith, done) {
35 | if (!options.directory && !options.extension && !options.transform) return done(new Error('metalsmith-copy: "directory" or "extension" option required'));
36 | if (!options.force) options.force = false;
37 |
38 | Object.keys(files).forEach(function (file) {
39 | debug('checking file: ' + file);
40 | var newName = file;
41 |
42 | // transform filename
43 | if (options.transform) {
44 | newName = options.transform(file);
45 | } else {
46 | if (options.extension) {
47 | var currentExt = path.extname(file);
48 | newName = path.join(path.dirname(file), path.basename(file, currentExt) + options.extension);
49 | }
50 | if (options.directory) {
51 | newName = path.join(options.directory, path.basename(newName));
52 | }
53 | }
54 |
55 | if (newName === file) {
56 | return;
57 | }
58 |
59 | if (files[newName] && options.force === false) return done(new Error('metalsmith-copy: copying ' + file + ' to ' + newName + ' would overwrite file'));
60 |
61 | debug('copying file: ' + newName);
62 | files[newName] = cloneDeep(files[file], function(value) {
63 | if (value instanceof Buffer) {
64 | return new Buffer(value);
65 | }
66 | });
67 | if (options.move) {
68 | delete files[file];
69 | }
70 | });
71 |
72 | done();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/meta.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const fs = require('fs')
3 | const metalsmith = require('./metalsmith')
4 |
5 | const {
6 | sortDependencies,
7 | installDependencies,
8 | runLintFix,
9 | printMessage,
10 | } = require('./utils')
11 | const pkg = require('./package.json')
12 |
13 | const templateVersion = pkg.version
14 |
15 | const { addTestAnswers } = require('./scenarios')
16 |
17 | module.exports = {
18 | metalsmith: {
19 | // When running tests for the template, this adds answers for the selected scenario
20 | before: addTestAnswers,
21 | after: metalsmith
22 | },
23 | helpers: {
24 | if_or(v1, v2, options) {
25 |
26 | if (v1 || v2) {
27 | return options.fn(this)
28 | }
29 |
30 | return options.inverse(this)
31 | },
32 | template_version() {
33 | return templateVersion
34 | },
35 | },
36 |
37 | prompts: {
38 | name: {
39 | when: 'isNotTest',
40 | type: 'string',
41 | required: true,
42 | message: 'Project name',
43 | },
44 | description: {
45 | when: 'isNotTest',
46 | type: 'string',
47 | required: false,
48 | message: 'Project description',
49 | default: 'A Vue.js project',
50 | },
51 | author: {
52 | when: 'isNotTest',
53 | type: 'string',
54 | message: 'Author',
55 | },
56 | projectType: {
57 | when: 'isNotTest',
58 | type: 'list',
59 | message: 'Project type',
60 | choices: [
61 | {
62 | name: 'Application (Targets end users)',
63 | value: 'app',
64 | short: 'Application'
65 | },
66 | {
67 | name: 'Library (Targets developers, includes demo application)',
68 | value: 'lib',
69 | short: 'Library'
70 | }
71 | ]
72 | },
73 | build: {
74 | when: 'isNotTest',
75 | type: 'list',
76 | message: 'Vue build',
77 | choices: [
78 | {
79 | name: 'Runtime + Compiler: recommended for most users',
80 | value: 'standalone',
81 | short: 'standalone',
82 | },
83 | {
84 | name:
85 | 'Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - render functions are required elsewhere',
86 | value: 'runtime',
87 | short: 'runtime',
88 | },
89 | ],
90 | },
91 | router: {
92 | when: 'isNotTest',
93 | type: 'confirm',
94 | message: 'Install vue-router?',
95 | },
96 | sfcExternals: {
97 | when: 'isNotTest',
98 | type: 'checkbox',
99 | message: 'Which tag do you want to externalize as standalone file from Single File Components ?',
100 | choices: [
101 | {
102 | name: '{{/if_eq}}{{#if_eq compiler "es2015"}}{{/if_eq}}
47 |
48 |
58 |
--------------------------------------------------------------------------------
/template/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Toilal/vue-webpack-template/c7dc0e8ee3e949a85342769bee5623b51d648b5c/template/src/assets/logo.png
--------------------------------------------------------------------------------
/template/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
\{{ msg }}
4 |
Essential Links
5 |
48 |
Ecosystem
49 |
83 |
84 |
85 | {{#if_eq compiler "typescript"}}{{/if_eq}}{{#if_eq compiler "es2015"}}{{/if_eq}}
116 |
117 |
118 |
134 |
--------------------------------------------------------------------------------
/template/src/hooks.js:
--------------------------------------------------------------------------------
1 | // Use this file to register components custom hooks.
2 | // @see https://github.com/vuejs/vue-class-component#adding-custom-hooks
3 | {{#router}}
4 | import Component from 'vue-class-component'
5 |
6 | {{/router}}
7 | {{#router}}
8 | // Register the router hooks with their names
9 | Component.registerHooks([
10 | 'beforeRouteEnter',
11 | 'beforeRouteLeave',
12 | 'beforeRouteUpdate'
13 | ])
14 | {{/router}}
15 |
16 | // Workaround for https://github.com/babel/babel-loader/issues/188
17 | export default undefined
18 |
--------------------------------------------------------------------------------
/template/src/hooks.ts:
--------------------------------------------------------------------------------
1 | // Use this file to register components custom hooks.
2 | // @see https://github.com/vuejs/vue-class-component#adding-custom-hooks
3 | {{#router}}
4 | import Component from 'vue-class-component'
5 |
6 | {{/router}}
7 | {{#router}}
8 | // Register the router hooks with their names
9 | Component.registerHooks([
10 | 'beforeRouteEnter',
11 | 'beforeRouteLeave',
12 | 'beforeRouteUpdate'
13 | ])
14 | {{/router}}
15 |
16 | // Workaround for https://github.com/babel/babel-loader/issues/188
17 | export default undefined
18 |
--------------------------------------------------------------------------------
/template/src/index.lib.js:
--------------------------------------------------------------------------------
1 | import HelloWorld from './components/HelloWorld.vue'
2 |
3 | export default HelloWorld
4 |
--------------------------------------------------------------------------------
/template/src/index.lib.ts:
--------------------------------------------------------------------------------
1 | import HelloWorld from './components/HelloWorld'
2 |
3 | export default HelloWorld
4 |
--------------------------------------------------------------------------------
/template/src/main.js:
--------------------------------------------------------------------------------
1 | {{#if_eq build "standalone"}}
2 | // The Vue build version to load with the `import` command
3 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
4 | {{/if_eq}}
5 | import Vue from 'vue'
6 | {{#classStyle}}
7 | import './hooks' // This must be imported before any component
8 |
9 | {{/classStyle}}
10 | import App from './App'
11 | {{#router}}
12 | import router from './router'
13 | {{/router}}
14 |
15 | Vue.config.productionTip = false
16 |
17 | /* eslint-disable no-new */
18 | new Vue({
19 | el: '#app',
20 | {{#router}}
21 | router,
22 | {{/router}}
23 | {{#if_eq build "runtime"}}
24 | render: h => h(App)
25 | {{/if_eq}}
26 | {{#if_eq build "standalone"}}
27 | components: { App },
28 | template: ''
29 | {{/if_eq}}
30 | })
31 |
--------------------------------------------------------------------------------
/template/src/main.ts:
--------------------------------------------------------------------------------
1 | {{#if_eq build 'standalone'}}
2 | // The Vue build version to load with the `import` command
3 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
4 | {{/if_eq}}
5 | import Vue from 'vue'
6 | {{#classStyle}}
7 | import './hooks' // This must be imported before any component
8 |
9 | {{/classStyle}}
10 | import App from './App'
11 | {{#router}}
12 | import router from './router'
13 | {{/router}}
14 |
15 | Vue.config.productionTip = false
16 |
17 | // tslint:disable-next-line:no-unused-expression
18 | new Vue({
19 | {{#router}}
20 | router,
21 | {{/router}}
22 | el: '#app',
23 | {{#if_eq build 'runtime'}}
24 | render: (h) => h(App)
25 | {{/if_eq}}
26 | {{#if_eq build 'standalone'}}
27 | components: { App },
28 | template: ''
29 | {{/if_eq}}
30 | })
31 |
--------------------------------------------------------------------------------
/template/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import HelloWorld from '@/components/HelloWorld'
4 |
5 | Vue.use(Router)
6 |
7 | export default new Router({
8 | routes: [
9 | {
10 | path: '/',
11 | name: 'HelloWorld',
12 | component: HelloWorld
13 | }
14 | ]
15 | })
16 |
--------------------------------------------------------------------------------
/template/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import HelloWorld from '@/components/HelloWorld'
4 |
5 | Vue.use(Router)
6 |
7 | export default new Router({
8 | routes: [
9 | {
10 | path: '/',
11 | name: 'HelloWorld',
12 | component: HelloWorld
13 | }
14 | ]
15 | })
16 |
--------------------------------------------------------------------------------
/template/src/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue'
3 | export default Vue
4 | }
5 |
--------------------------------------------------------------------------------
/template/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Toilal/vue-webpack-template/c7dc0e8ee3e949a85342769bee5623b51d648b5c/template/static/.gitkeep
--------------------------------------------------------------------------------
/template/test/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // The assertion name is the filename.
3 | // Example usage:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // For more information on custom assertions see:
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 |
10 | exports.assertion = function (selector, count) {
11 | this.message = 'Testing if element <' + selector + '> has count: ' + count
12 | this.expected = count
13 | this.pass = function (val) {
14 | return val === this.expected
15 | }
16 | this.value = function (res) {
17 | return res.value
18 | }
19 | this.command = function (cb) {
20 | var self = this
21 | return this.api.execute(function (selector) {
22 | return document.querySelectorAll(selector).length
23 | }, [selector], function (res) {
24 | cb.call(self, res)
25 | })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/template/test/e2e/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-register')
2 | var config = require('../../config')
3 |
4 | // http://nightwatchjs.org/gettingstarted#settings-file
5 | module.exports = {
6 | src_folders: ['test/e2e/specs'],
7 | output_folder: 'test/e2e/reports',
8 | custom_assertions_path: ['test/e2e/custom-assertions'],
9 |
10 | selenium: {
11 | start_process: true,
12 | server_path: require('selenium-server').path,
13 | host: '127.0.0.1',
14 | port: 4444,
15 | cli_args: {
16 | 'webdriver.chrome.driver': require('chromedriver').path
17 | }
18 | },
19 |
20 | test_settings: {
21 | default: {
22 | selenium_port: 4444,
23 | selenium_host: 'localhost',
24 | silent: true,
25 | globals: {
26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
27 | }
28 | },
29 |
30 | chrome: {
31 | desiredCapabilities: {
32 | browserName: 'chrome',
33 | javascriptEnabled: true,
34 | acceptSslCerts: true
35 | }
36 | },
37 |
38 | firefox: {
39 | desiredCapabilities: {
40 | browserName: 'firefox',
41 | javascriptEnabled: true,
42 | acceptSslCerts: true
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/template/test/e2e/runner.js:
--------------------------------------------------------------------------------
1 | // 1. start the dev server using production config
2 | process.env.NODE_ENV = 'testing'
3 |
4 | const webpack = require('webpack')
5 | const DevServer = require('webpack-dev-server')
6 |
7 | const webpackConfig = require('../../build/webpack.prod.conf')
8 | const devConfigPromise = require('../../build/webpack.dev.conf')
9 |
10 | let server
11 |
12 | devConfigPromise.then(devConfig => {
13 | const devServerOptions = devConfig.devServer
14 | const compiler = webpack(webpackConfig)
15 | server = new DevServer(compiler, devServerOptions)
16 | const port = devServerOptions.port
17 | const host = devServerOptions.host
18 | return server.listen(port, host)
19 | })
20 | .then(() => {
21 | // 2. run the nightwatch test suite against it
22 | // to run in additional browsers:
23 | // 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
24 | // 2. add it to the --env flag below
25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
26 | // For more information on Nightwatch's config file, see
27 | // http://nightwatchjs.org/guide#settings-file
28 | let opts = process.argv.slice(2)
29 | if (opts.indexOf('--config') === -1) {
30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
31 | }
32 | if (opts.indexOf('--env') === -1) {
33 | opts = opts.concat(['--env', 'chrome'])
34 | }
35 |
36 | const spawn = require('cross-spawn')
37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
38 |
39 | runner.on('exit', function (code) {
40 | server.close()
41 | process.exit(code)
42 | })
43 |
44 | runner.on('error', function (err) {
45 | server.close()
46 | throw err
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/template/test/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': function {{#if_eq lintConfig "airbnb"}}test{{/if_eq}}(browser) {
6 | // automatically uses dev Server port from /config.index.js
7 | // default: http://localhost:8080
8 | // see nightwatch.conf.js
9 | const devServer = browser.globals.devServerURL
10 |
11 | browser
12 | .url(devServer)
13 | .waitForElementVisible('#app', 5000)
14 | .assert.elementPresent('.hello')
15 | .assert.containsText('h1', 'Welcome to Your Vue.js App')
16 | .assert.elementCount('img', 1)
17 | .end()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/template/test/unit/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": { {{#if_eq runner "karma"}}
3 | "mocha": true{{/if_eq}}{{#if_eq runner "jest"}}
4 | "jest": true{{/if_eq}}
5 | },
6 | "globals": { {{#if_eq runner "karma"}}
7 | "expect": true,
8 | "sinon": true{{/if_eq}}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/template/test/unit/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | Vue.config.productionTip = false
4 |
5 | // require all test files (files that ends with .spec.js)
6 | const testsContext = require.context('./specs', true, /\.spec$/)
7 | testsContext.keys().forEach(testsContext)
8 |
9 | // require all src files except main.js for coverage.
10 | // you can also change this to match only the subset of files that
11 | // you want coverage for.
12 | const srcContext = require.context('../../src', true, {{#if_eq compiler "typescript"}}/^\.\/(?!(?:main|.*?\.d)(\.ts)?$)/{{else}}/^\.\/(?!main(\.js)?$)/{{/if_eq}})
13 | srcContext.keys().forEach(srcContext)
14 |
--------------------------------------------------------------------------------
/template/test/unit/jest.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | rootDir: path.resolve(__dirname, '../../'),
5 | moduleDirectories: ['node_modules', 'src'],
6 | moduleFileExtensions: [
7 | 'vue',
8 | 'js',{{#if_eq compiler "typescript"}}
9 | 'ts',{{/if_eq}}
10 | 'json'
11 | ],
12 | moduleNameMapper: {
13 | '^@/(.*)$': '/src/$1'{{#if_eq projectType "lib"}},
14 | '^#/(.*)$': '/app/$1'{{/if_eq}}
15 | },
16 | transform: {
17 | '^.+\\.js$': '/node_modules/babel-jest',{{#if_eq compiler "typescript"}}
18 | '^.+(?:!\\.d|)\\.ts$': '/node_modules/ts-jest',{{/if_eq}}
19 | '.*\\.(vue)$': '/node_modules/vue-jest'
20 | },{{#if_eq compiler "typescript"}}
21 | testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',{{/if_eq}}{{#e2e}}
22 | testPathIgnorePatterns: [
23 | '/test/e2e'
24 | ],{{/e2e}}
25 | snapshotSerializers: ['/node_modules/jest-serializer-vue'],
26 | setupFiles: ['/test/unit/setup'],
27 | mapCoverage: true,
28 | coverageDirectory: '/test/unit/coverage',
29 | collectCoverageFrom: [
30 | 'src/**/*.{js,{{#if_eq compiler "typescript"}}ts,{{/if_eq}}vue}',{{#if_eq compiler "typescript"}}
31 | '!src/**/*.d.ts',{{/if_eq}}
32 | '!src/main.{{#if_eq compiler "typescript"}}{js,ts}{{else}}js{{/if_eq}}',
33 | {{#router}}
34 | '!src/router/index.{{#if_eq compiler "typescript"}}{js,ts}{{else}}js{{/if_eq}}',
35 | {{/router}}
36 | '!**/node_modules/**'
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/template/test/unit/karma.conf.js:
--------------------------------------------------------------------------------
1 | // This is a karma config file. For more details see
2 | // http://karma-runner.github.io/0.13/config/configuration-file.html
3 | // we are also using it with karma-webpack
4 | // https://github.com/webpack/karma-webpack
5 |
6 | var webpackConfig = require('../../build/webpack.test.conf')
7 |
8 | module.exports = function karmaConfig (config) {
9 | config.set({
10 | // to run in additional browsers:
11 | // 1. install corresponding karma launcher
12 | // http://karma-runner.github.io/0.13/config/browsers.html
13 | // 2. add it to the `browsers` array below.
14 | browsers: ['PhantomJS'],
15 | frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
16 | reporters: ['spec', 'coverage', 'remap-coverage'],
17 | files: ['./index.js'],
18 | preprocessors: {
19 | './index.js': ['webpack', 'sourcemap']
20 | },
21 | webpack: webpackConfig,
22 | webpackMiddleware: {
23 | noInfo: true
24 | },
25 | coverageReporter: {
26 | type: 'in-memory'
27 | },
28 | {{#if_eq compiler "es2015"}}
29 | remapOptions: {
30 | warn: function(warn) { // Disable remap warnings (when no sourcemap is found)
31 | if (typeof warn !== "string") {
32 | warn = warn.toString();
33 | }
34 | if (warn.indexOf("Could not find source map for") === -1) {
35 | console.warn.apply(this, arguments)
36 | }
37 | }
38 | },
39 | {{/if_eq}}
40 | remapCoverageReporter: {
41 | 'text-summary': null,
42 | lcovonly: './test/unit/coverage/lcov.info',
43 | html: './test/unit/coverage/lcov-report'
44 | }
45 | })
46 | }
47 |
--------------------------------------------------------------------------------
/template/test/unit/setup.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | Vue.config.productionTip = false
4 |
--------------------------------------------------------------------------------
/template/test/unit/specs/HelloWorld.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import HelloWorld from '@/components/HelloWorld'
3 |
4 | describe('HelloWorld.vue', () => {
5 | it('should render correct contents', () => {
6 | const Constructor = Vue.extend(HelloWorld)
7 | const vm = new Constructor().$mount()
8 | expect(vm.$el.querySelector('.hello h1').textContent)
9 | {{#if_eq runner "karma"}}.to.equal('Welcome to Your Vue.js App'){{/if_eq}}{{#if_eq runner "jest"}}.toEqual('Welcome to Your Vue.js App'){{/if_eq}}
10 | })
11 | })
12 |
--------------------------------------------------------------------------------
/template/test/unit/specs/HelloWorld.spec.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import HelloWorld from '@/components/HelloWorld.vue'{{#if_eq runner "karma"}}
3 | import { expect } from 'chai'{{/if_eq}}
4 |
5 | describe('HelloWorld.vue', () => {
6 | it('should render correct contents', () => {
7 | const Constructor = Vue.extend(HelloWorld)
8 | const vm = new Constructor().$mount()
9 | expect(vm.$el.querySelector('.hello h1')!.textContent)
10 | {{#if_eq runner "karma"}}.to.equal('Welcome to Your Vue.js App'){{/if_eq}}{{#if_eq runner "jest"}}.toEqual('Welcome to Your Vue.js App'){{/if_eq}}
11 | })
12 | })
13 |
--------------------------------------------------------------------------------
/template/test/unit/typings.d.ts:
--------------------------------------------------------------------------------
1 | interface WebpackRequire extends NodeRequire {
2 | context (file: string, flag?: boolean, exp?: RegExp): any
3 | }
4 |
--------------------------------------------------------------------------------
/template/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "@/*": ["src/*"]{{#if_eq projectType "lib"}},
6 | "#/*": ["app/*"]{{/if_eq}}
7 | },
8 | "sourceMap": true,
9 | "experimentalDecorators": true,
10 | "allowSyntheticDefaultImports": true,
11 | "target": "es6",
12 | "module": "es2015",
13 | "moduleResolution": "node",
14 | "lib": ["dom", "es2017"],
15 | "strict": true,
16 | "types": [
17 | {{#if_eq runner "jest"}}
18 | "jest",{{/if_eq}}{{#if_eq runner "karma"}}
19 | "chai",
20 | "mocha",
21 | "sinon",
22 | "sinon-chai",{{/if_eq}}
23 | "node",
24 | "vue"
25 | ],
26 | "typeRoots": [
27 | "./node_modules/@types"
28 | ]
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/template/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | {{#if_eq tslintConfig "none"}}
3 | "rules": {}
4 | {{/if_eq}}
5 | {{#if_eq tslintConfig "standard"}}
6 | "extends": "tslint-config-standard",
7 | "rules": {}
8 | {{/if_eq}}
9 | {{#if_eq tslintConfig "airbnb"}}
10 | "extends": "tslint-config-airbnb",
11 | "rules": {
12 | "import-name": false,
13 | "object-shorthand-properties-first": false,
14 | "variable-name": [true, "allow-pascal-case"]
15 | }
16 | {{/if_eq}}
17 | }
18 |
--------------------------------------------------------------------------------
/utils/index.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const fs = require('fs')
3 | const spawn = require('child_process').spawn
4 |
5 | const lintStyles = ['standard', 'airbnb']
6 |
7 | /**
8 | * Sorts dependencies in package.json alphabetically.
9 | * They are unsorted because they were grouped for the handlebars helpers
10 | * @param {object} data Data from questionnaire
11 | */
12 | exports.sortDependencies = function sortDependencies(data) {
13 | const packageJsonFile = path.join(
14 | data.inPlace ? '' : data.destDirName,
15 | 'package.json'
16 | )
17 | const packageJson = JSON.parse(fs.readFileSync(packageJsonFile))
18 | packageJson.devDependencies = sortObject(packageJson.devDependencies)
19 | packageJson.dependencies = sortObject(packageJson.dependencies)
20 | fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2) + '\n')
21 | }
22 |
23 | /**
24 | * Runs `npm install` in the project directory
25 | * @param {string} cwd Path of the created project directory
26 | * @param {object} data Data from questionnaire
27 | */
28 | exports.installDependencies = function installDependencies(
29 | cwd,
30 | executable = 'npm',
31 | color
32 | ) {
33 | console.log(`\n\n# ${color('Installing project dependencies ...')}`)
34 | console.log('# ========================\n')
35 | return runCommand(executable, ['install'], {
36 | cwd,
37 | })
38 | }
39 |
40 | /**
41 | * Runs `npm run lint -- --fix` in the project directory
42 | * @param {string} cwd Path of the created project directory
43 | * @param {object} data Data from questionnaire
44 | */
45 | exports.runLintFix = function runLintFix(cwd, data, color) {
46 | if (data.lint && lintStyles.indexOf(data.lintConfig) !== -1) {
47 | console.log(
48 | `\n\n${color(
49 | 'Running eslint --fix to comply with chosen preset rules...'
50 | )}`
51 | )
52 | console.log('# ========================\n')
53 | const args =
54 | data.autoInstall === 'npm'
55 | ? ['run', 'lint', '--', '--fix']
56 | : ['run', 'lint', '--fix']
57 | return runCommand(data.autoInstall, args, {
58 | cwd,
59 | })
60 | }
61 | return Promise.resolve()
62 | }
63 |
64 | /**
65 | * Prints the final message with instructions of necessary next steps.
66 | * @param {Object} data Data from questionnaire.
67 | */
68 | exports.printMessage = function printMessage(data, { green, yellow }) {
69 | const message = `
70 | # ${green('Project initialization finished!')}
71 | # ========================
72 |
73 | To get started:
74 |
75 | ${yellow(
76 | `${data.inPlace ? '' : `cd ${data.destDirName}\n `}${installMsg(
77 | data
78 | )}${lintMsg(data)}npm run dev`
79 | )}
80 |
81 | Documentation can be found at https://vuejs-templates.github.io/webpack
82 | `
83 | console.log(message)
84 | }
85 |
86 | /**
87 | * If the user will have to run lint --fix themselves, it returns a string
88 | * containing the instruction for this step.
89 | * @param {Object} data Data from questionnaire.
90 | */
91 | function lintMsg(data) {
92 | return !data.autoInstall &&
93 | data.lint &&
94 | lintStyles.indexOf(data.lintConfig) !== -1
95 | ? 'npm run lint -- --fix (or for yarn: yarn run lint --fix)\n '
96 | : ''
97 | }
98 |
99 | /**
100 | * If the user will have to run `npm install` or `yarn` themselves, it returns a string
101 | * containing the instruction for this step.
102 | * @param {Object} data Data from the questionnaire
103 | */
104 | function installMsg(data) {
105 | return !data.autoInstall ? 'npm install (or if using yarn: yarn)\n ' : ''
106 | }
107 |
108 | /**
109 | * Spawns a child process and runs the specified command
110 | * By default, runs in the CWD and inherits stdio
111 | * Options are the same as node's child_process.spawn
112 | * @param {string} cmd
113 | * @param {array} args
114 | * @param {object} options
115 | */
116 | function runCommand(cmd, args, options) {
117 | return new Promise((resolve, reject) => {
118 | const spwan = spawn(
119 | cmd,
120 | args,
121 | Object.assign(
122 | {
123 | cwd: process.cwd(),
124 | stdio: 'inherit',
125 | shell: true,
126 | },
127 | options
128 | )
129 | )
130 |
131 | spwan.on('exit', () => {
132 | resolve()
133 | })
134 | })
135 | }
136 |
137 | function sortObject(object) {
138 | // Based on https://github.com/yarnpkg/yarn/blob/v1.3.2/src/config.js#L79-L85
139 | const sortedObject = {}
140 | Object.keys(object)
141 | .sort()
142 | .forEach(item => {
143 | sortedObject[item] = object[item]
144 | })
145 | return sortedObject
146 | }
147 |
--------------------------------------------------------------------------------