diff --git a/docs/packages/vue/README.md b/docs/packages/vue/README.md new file mode 100644 index 000000000..db1fa49c7 --- /dev/null +++ b/docs/packages/vue/README.md @@ -0,0 +1,256 @@ +# Neutrino Vue Preset + +[![NPM version][npm-image]][npm-url] +[![NPM downloads][npm-downloads]][npm-url] +[![Join the Neutrino community on Spectrum][spectrum-image]][spectrum-url] + +## Features + +- Zero upfront configuration necessary to start developing and building a Vue web app +- Modern Babel compilation. +- Extends from [@neutrinojs/web](../web) + - Modern Babel compilation supporting ES modules, last 2 major browser versions, async functions, and dynamic imports + - Webpack loaders for importing HTML, CSS, images, icons, fonts, and web workers + - Webpack Dev Server during development + - Automatic creation of HTML pages, no templating necessary + - Hot Module Replacement support + - Tree-shaking to create smaller bundles + - Production-optimized bundles with Babili minification, easy chunking, and scope-hoisted modules for faster execution + - Easily extensible to customize your project as needed + +## Requirements + +- Node.js v6.10+ +- Yarn or npm client +- Neutrino v7 + +## Installation + +`@neutrinojs/vue` can be installed via the Yarn or npm clients. Inside your project, make sure +`neutrino` and `@neutrinojs/vue` are development dependencies. You will also need Vue for actual +Vue development. + +#### Yarn + +```bash +❯ yarn add --dev neutrino @neutrinojs/vue +❯ yarn add vue +``` + +#### npm + +```bash +❯ npm install --save-dev neutrino @neutrinojs/vue +❯ npm install --save vue + + +## Project Layout + +`@neutrinojs/vue` follows the standard [project layout](../../project-layout) specified by Neutrino. This +means that by default all project source code should live in a directory named `src` in the root of the +project. This includes JavaScript files, CSS stylesheets, images, and any other assets that would be available +to import your compiled project. + +## Quickstart + +After installing Neutrino and the Vue preset, add a new directory named `src` in the root of the project, with +two files `index.js` and `App.vue` in it. + +```bash +❯ mkdir src && touch src/index.js && touch src/App.vue +``` + +This Vue preset exposes an element in the page with an ID of `root` to which you can mount your application. Edit +your `src/index.js` file with the following: + +```js +import Vue from 'vue'; +import App from './App.vue'; + +new Vue({ + el: '#root', + render: (h) => h(App), +}); +``` + +Next, edit your `src/App.vue` with the following: + +```html + + + +``` + +Now edit your project's package.json to add commands for starting and building the application: + +```json +{ + "scripts": { + "start": "neutrino start --use @neutrinojs/vue", + "build": "neutrino build --use @neutrinojs/vue" + } +} +``` + +If you are using `.neutrinorc.js`, add this preset to your use array instead of `--use` flags: + +```js +module.exports = { + use: ['@neutrinojs/vue'] +}; +``` + +#### Yarn + +```bash +❯ yarn start +✔ Development server running on: http://localhost:5000 +✔ Build completed +``` + +#### npm + +```bash +❯ npm start +✔ Development server running on: http://localhost:5000 +✔ Build completed +``` + +Start the app, then open a browser to the address in the console: + +## Building + +`@neutrinojs/vue` builds static assets to the `build` directory by default when running `neutrino build`. Using +the quick start example above as a reference: + +```bash +❯ yarn build + +✔ Building project completed +Hash: b26ff013b5a2d5f7b824 +Version: webpack 3.5.6 +Time: 9773ms + Asset Size Chunks Chunk Names + index.dfbad882ab3d86bfd747.js 181 kB index [emitted] index + runtime.3d9f9d2453f192a2b10f.js 1.51 kB runtime [emitted] runtime + index.html 846 bytes [emitted] +✨ Done in 14.62s. +``` + +You can either serve or deploy the contents of this `build` directory as a static site. + +## Static assets + +If you wish to copy files to the build directory that are not imported from application code, you can place +them in a directory within `src` called `static`. All files in this directory will be copied from `src/static` +to `build/static`. To change this behavior, specify your own patterns with +[@neutrinojs/copy](../copy). + +## Paths + +The `@neutrinojs/web` preset loads assets relative to the path of your application by setting Webpack's +[`output.publicPath`](https://webpack.js.org/configuration/output/#output-publicpath) to `./`. If you wish to load +assets instead from a CDN, or if you wish to change to an absolute path for your application, customize your build to +override `output.publicPath`. See the [Customizing](#Customizing) section below. + + +## Preset options + +You can provide custom options and have them merged with this preset's default options to easily affect how this +preset builds. You can modify Vue preset settings from `.neutrinorc.js` by overriding with an options object. Use +an array pair instead of a string to supply these options in `.neutrinorc.js`. + +The following shows how you can pass an options object to the Vue preset and override its options. See the +[Web documentation](../web#preset-options) for specific options you can override with this object. + +```js +module.exports = { + use: [ + ['@neutrinojs/vue', { + /* preset options */ + + // Example: disable Hot Module Replacement + hot: false, + + // Example: change the page title + html: { + title: 'Epic Vue App' + }, + + // Target specific browsers with babel-preset-env + targets: { + browsers: [ + 'last 1 Chrome versions', + 'last 1 Firefox versions' + ] + }, + + // Add additional Babel plugins, presets, or env options + babel: { + // Override options for babel-preset-env: + presets: [ + ['babel-preset-env', { + modules: false, + useBuiltIns: true, + exclude: ['transform-regenerator', 'transform-async-to-generator'], + }] + ] + } + }] + ] +}; +``` + +## Customizing + +To override the build configuration, start with the documentation on [customization](../../customization). +`@neutrinojs/vue` does not use any additional named rules, loaders, or plugins that aren't already in use by the +Web preset. See the [Web documentation customization](../web#customizing) +for preset-specific configuration to override. + +### Advanced configuration + +By following the [customization guide](../../customization) and knowing the rule, loader, and plugin IDs from +`@neutrinojs/web`, you can override and augment the build by providing a function to your `.neutrinorc.js` use +array. You can also make these changes from the Neutrino API in custom middleware. + +#### Vendoring + +By defining an entry point named `vendor` you can split out external dependencies into a chunk separate +from your application code. + +_Example: Put Vue into a separate "vendor" chunk:_ + +```js +module.exports = { + use: [ + '@neutrinojs/vue', + (neutrino) => neutrino.config + .entry('vendor') + .add('vue') + ] +}; +``` + +## Contributing + +This preset is part of the [neutrino-dev](https://github.com/mozilla-neutrino/neutrino-dev) repository, a monorepo +containing all resources for developing Neutrino and its core presets and middleware. Follow the +[contributing guide](../../contributing) for details. + +[npm-image]: https://img.shields.io/npm/v/@neutrinojs/vue.svg +[npm-downloads]: https://img.shields.io/npm/dt/@neutrinojs/vue.svg +[npm-url]: https://npmjs.org/package/@neutrinojs/vue +[spectrum-image]: https://withspectrum.github.io/badge/badge.svg +[spectrum-url]: https://spectrum.chat/neutrino diff --git a/packages/neutrino/src/api.js b/packages/neutrino/src/api.js index 3269fec1c..b9c10a65f 100644 --- a/packages/neutrino/src/api.js +++ b/packages/neutrino/src/api.js @@ -26,6 +26,7 @@ const pathOptions = [ // getOptions :: Object? -> IO Object const getOptions = (opts = {}) => { + let moduleExtensions = new Set(['js', 'jsx', 'vue', 'ts', 'mjs', 'json']); const options = merge({ env: { NODE_ENV: 'development' @@ -34,6 +35,16 @@ const getOptions = (opts = {}) => { quiet: false }, opts); + Object.defineProperty(options, 'extensions', { + enumerable: true, + get() { + return [...moduleExtensions]; + }, + set(extensions) { + moduleExtensions = new Set(extensions.map(ext => ext.replace('.', ''))); + } + }); + Object .keys(options.env) .forEach(env => process.env[env] = options.env[env]); @@ -87,6 +98,10 @@ class Api { this.config = new Config(); } + regexFromExtensions(extensions = this.options.extensions) { + return new RegExp(`.(${extensions.join('|')})$`); + } + emit(...args) { return this.emitter.emit(...args); } diff --git a/packages/vue/.npmignore b/packages/vue/.npmignore new file mode 100644 index 000000000..193378602 --- /dev/null +++ b/packages/vue/.npmignore @@ -0,0 +1 @@ +/test/ diff --git a/packages/vue/README.md b/packages/vue/README.md new file mode 100644 index 000000000..9f7945388 --- /dev/null +++ b/packages/vue/README.md @@ -0,0 +1,256 @@ +# Neutrino Vue Preset + +[![NPM version][npm-image]][npm-url] +[![NPM downloads][npm-downloads]][npm-url] +[![Join the Neutrino community on Spectrum][spectrum-image]][spectrum-url] + +## Features + +- Zero upfront configuration necessary to start developing and building a Vue web app +- Modern Babel compilation. +- Extends from [@neutrinojs/web](https://neutrino.js.org/packages/web) + - Modern Babel compilation supporting ES modules, last 2 major browser versions, async functions, and dynamic imports + - Webpack loaders for importing HTML, CSS, images, icons, fonts, and web workers + - Webpack Dev Server during development + - Automatic creation of HTML pages, no templating necessary + - Hot Module Replacement support + - Tree-shaking to create smaller bundles + - Production-optimized bundles with Babili minification, easy chunking, and scope-hoisted modules for faster execution + - Easily extensible to customize your project as needed + +## Requirements + +- Node.js v6.10+ +- Yarn or npm client +- Neutrino v7 + +## Installation + +`@neutrinojs/vue` can be installed via the Yarn or npm clients. Inside your project, make sure +`neutrino` and `@neutrinojs/vue` are development dependencies. You will also need Vue for actual +Vue development. + +#### Yarn + +```bash +❯ yarn add --dev neutrino @neutrinojs/vue +❯ yarn add vue +``` + +#### npm + +```bash +❯ npm install --save-dev neutrino @neutrinojs/vue +❯ npm install --save vue + + +## Project Layout + +`@neutrinojs/vue` follows the standard [project layout](https://neutrino.js.org/project-layout) specified by Neutrino. This +means that by default all project source code should live in a directory named `src` in the root of the +project. This includes JavaScript files, CSS stylesheets, images, and any other assets that would be available +to import your compiled project. + +## Quickstart + +After installing Neutrino and the Vue preset, add a new directory named `src` in the root of the project, with +two files `index.js` and `App.vue` in it. + +```bash +❯ mkdir src && touch src/index.js && touch src/App.vue +``` + +This Vue preset exposes an element in the page with an ID of `root` to which you can mount your application. Edit +your `src/index.js` file with the following: + +```js +import Vue from 'vue'; +import App from './App.vue'; + +new Vue({ + el: '#root', + render: (h) => h(App), +}); +``` + +Next, edit your `src/App.vue` with the following: + +```html + + + +``` + +Now edit your project's package.json to add commands for starting and building the application: + +```json +{ + "scripts": { + "start": "neutrino start --use @neutrinojs/vue", + "build": "neutrino build --use @neutrinojs/vue" + } +} +``` + +If you are using `.neutrinorc.js`, add this preset to your use array instead of `--use` flags: + +```js +module.exports = { + use: ['@neutrinojs/vue'] +}; +``` + +#### Yarn + +```bash +❯ yarn start +✔ Development server running on: http://localhost:5000 +✔ Build completed +``` + +#### npm + +```bash +❯ npm start +✔ Development server running on: http://localhost:5000 +✔ Build completed +``` + +Start the app, then open a browser to the address in the console: + +## Building + +`@neutrinojs/vue` builds static assets to the `build` directory by default when running `neutrino build`. Using +the quick start example above as a reference: + +```bash +❯ yarn build + +✔ Building project completed +Hash: b26ff013b5a2d5f7b824 +Version: webpack 3.5.6 +Time: 9773ms + Asset Size Chunks Chunk Names + index.dfbad882ab3d86bfd747.js 181 kB index [emitted] index + runtime.3d9f9d2453f192a2b10f.js 1.51 kB runtime [emitted] runtime + index.html 846 bytes [emitted] +✨ Done in 14.62s. +``` + +You can either serve or deploy the contents of this `build` directory as a static site. + +## Static assets + +If you wish to copy files to the build directory that are not imported from application code, you can place +them in a directory within `src` called `static`. All files in this directory will be copied from `src/static` +to `build/static`. To change this behavior, specify your own patterns with +[@neutrinojs/copy](https://neutrino.js.org/packages/copy). + +## Paths + +The `@neutrinojs/web` preset loads assets relative to the path of your application by setting Webpack's +[`output.publicPath`](https://webpack.js.org/configuration/output/#output-publicpath) to `./`. If you wish to load +assets instead from a CDN, or if you wish to change to an absolute path for your application, customize your build to +override `output.publicPath`. See the [Customizing](#Customizing) section below. + + +## Preset options + +You can provide custom options and have them merged with this preset's default options to easily affect how this +preset builds. You can modify Vue preset settings from `.neutrinorc.js` by overriding with an options object. Use +an array pair instead of a string to supply these options in `.neutrinorc.js`. + +The following shows how you can pass an options object to the Vue preset and override its options. See the +[Web documentation](https://neutrino.js.org/packages/web#preset-options) for specific options you can override with this object. + +```js +module.exports = { + use: [ + ['@neutrinojs/vue', { + /* preset options */ + + // Example: disable Hot Module Replacement + hot: false, + + // Example: change the page title + html: { + title: 'Epic Vue App' + }, + + // Target specific browsers with babel-preset-env + targets: { + browsers: [ + 'last 1 Chrome versions', + 'last 1 Firefox versions' + ] + }, + + // Add additional Babel plugins, presets, or env options + babel: { + // Override options for babel-preset-env: + presets: [ + ['babel-preset-env', { + modules: false, + useBuiltIns: true, + exclude: ['transform-regenerator', 'transform-async-to-generator'], + }] + ] + } + }] + ] +}; +``` + +## Customizing + +To override the build configuration, start with the documentation on [customization](https://neutrino.js.org/customization). +`@neutrinojs/vue` does not use any additional named rules, loaders, or plugins that aren't already in use by the +Web preset. See the [Web documentation customization](https://neutrino.js.org/packages/web#customizing) +for preset-specific configuration to override. + +### Advanced configuration + +By following the [customization guide](https://neutrino.js.org/customization) and knowing the rule, loader, and plugin IDs from +`@neutrinojs/web`, you can override and augment the build by providing a function to your `.neutrinorc.js` use +array. You can also make these changes from the Neutrino API in custom middleware. + +#### Vendoring + +By defining an entry point named `vendor` you can split out external dependencies into a chunk separate +from your application code. + +_Example: Put Vue into a separate "vendor" chunk:_ + +```js +module.exports = { + use: [ + '@neutrinojs/vue', + (neutrino) => neutrino.config + .entry('vendor') + .add('vue') + ] +}; +``` + +## Contributing + +This preset is part of the [neutrino-dev](https://github.com/mozilla-neutrino/neutrino-dev) repository, a monorepo +containing all resources for developing Neutrino and its core presets and middleware. Follow the +[contributing guide](https://neutrino.js.org/contributing) for details. + +[npm-image]: https://img.shields.io/npm/v/@neutrinojs/vue.svg +[npm-downloads]: https://img.shields.io/npm/dt/@neutrinojs/vue.svg +[npm-url]: https://npmjs.org/package/@neutrinojs/vue +[spectrum-image]: https://withspectrum.github.io/badge/badge.svg +[spectrum-url]: https://spectrum.chat/neutrino diff --git a/packages/vue/index.js b/packages/vue/index.js new file mode 100644 index 000000000..175e0a816 --- /dev/null +++ b/packages/vue/index.js @@ -0,0 +1,55 @@ +const loaderMerge = require('@neutrinojs/loader-merge'); +const web = require('@neutrinojs/web'); +const path = require('path'); +const merge = require('deepmerge'); + +const MODULES = path.join(__dirname, 'node_modules'); + +module.exports = (neutrino, options) => { + neutrino.use(web, options); + + neutrino.config.module + .rule('vue') + .test(neutrino.regexFromExtensions(['vue'])) + .use('vue') + .loader(require.resolve('vue-loader')) + .options(options); + + neutrino.config.when(neutrino.config.module.rules.has('lint'), () => { + neutrino.use(loaderMerge('lint', 'eslint'), { + plugins: ['vue'], + envs: ['node'], + parserOptions: { + ecmaFeatures: { + jsx: true + } + }, + rules: { + 'vue/jsx-uses-vars': 2 + } + }); + }); + + if (neutrino.config.plugins.has('stylelint')) { + neutrino.config.plugin('stylelint') + .tap(([options, ...args]) => [ + merge(options, { + files: ['**/*.vue'], + config: { + processors: [require.resolve('stylelint-processor-html')], + rules: { + // allows empty