├── README.md ├── bower.json ├── demo ├── README.md ├── app.build.js ├── app.dist.html ├── bower.json ├── index.html └── lib │ ├── clock.html │ ├── component-head.vue │ └── main.js ├── package.json └── requirejs-vue.js /README.md: -------------------------------------------------------------------------------- 1 | # requirejs-vue 2 | 3 | ![ECMAScript 5.1](https://img.shields.io/badge/es-5-brightgreen.svg) 4 | ![Github file size](https://img.shields.io/github/size/vikseriq/requirejs-vue/requirejs-vue.js.svg) 5 | 6 | A Vue.js [Single File Components](https://vuejs.org/v2/guide/single-file-components.html) loader plugin for 7 | [RequireJS](https://github.com/requirejs/requirejs). 8 | One-file, browser or server, no additional fats, es5+ compatible, no babels, gluten-free. 9 | 10 | ## Demo on [Plunker](https://plnkr.co/edit/Y2cEa3) 11 | 12 | On browser-side it uses XMLHttpRequest to fetch the .vue files, so you can only fetch files 13 | that are on the *same domain as the html page*. Most browsers place restrictions on using 14 | XMLHttpRequest from local file URLs, so use a web server to serve your ```.vue``` files. 15 | 16 | The server-side building with RequireJS Optimizer [r.js](https://github.com/requirejs/r.js) also available and works well. 17 | 18 | Plugin supports `pug` templates. Provide pug parser via module config. Tested with [browser-side pug renderer](https://github.com/vikseriq/browser-pug). 19 | 20 | Since another templating engines or css preprocessors (like [less](https://github.com/guybedford/require-less)/sass) 21 | not available as maintained AMD modules there are no plans to support them. Feel free to write your own 😉 22 | 23 | ## Install 24 | 25 | ### Via package manager 26 | 27 | To install with [yarn](https://github.com/yarnpkg/yarn) 28 | 29 | ``` 30 | yarn add requirejs-vue 31 | ``` 32 | 33 | Or good ol' ```npm```: 34 | ``` 35 | npm install --save requirejs-vue 36 | ``` 37 | 38 | And [Bower](http://bower.io/): 39 | 40 | ``` 41 | bower install requirejs-vue 42 | ``` 43 | 44 | ### Manual download 45 | 46 | Download the [latest version](https://rawgit.com/vikseriq/requirejs-vue/master/requirejs-vue.js). 47 | 48 | ## Usage 49 | 50 | Setup loader in RequireJS path like this: 51 | 52 | ... 53 | paths: { 54 | 'Vue': 'path to Vue.js', 55 | 'vue': 'path to requirejs-vue' 56 | }, 57 | config: { 58 | 'vue': { 59 | 'pug': 'browser-pug', 60 | 'css': 'inject' 61 | 'templateVar': 'template' 62 | } 63 | } 64 | ... 65 | 66 | 67 | Reference Vue file via the ```vue!```. 68 | For example, to load the `component.vue` file that is in your ```baseUrl``` directory: 69 | 70 | require(['vue!component'], function (component) { 71 | // 72 | }); 73 | 74 | You can specify any alias for loader but update paths alias too. 75 | 76 | 77 | ### Configuration 78 | 79 | Inside loaded file reference template by `templateVar` variable. 80 | Stylesheets controlled by `css` configuration value. Currently only global styles supported. 81 | Content of template will be cleared from whitespaces and comments. Nested `template` tags supported. 82 | 83 | Loader support ```.vue``` and ```.html``` files. 84 | 85 | 86 | #### `css` 87 | `String | Function`, default: `inject` 88 | 89 | Strategy to deal with component stylesheets. Variants: 90 | * `inject` - appending styles in new ` 121 | 128 | ``` 129 | 130 | ### Pug templates 131 | 132 | Using [browser-pug](https://github.com/vikseriq/browser-pug) it is possible to transpose 133 | basic `pug` markup as Vue template. To achieve do next steps: 134 | 135 | 1. Install ```browser-pug``` plugin 136 | 137 | ```bash 138 | yarn add browser-pug 139 | ``` 140 | 141 | 2. Setup module paths and configs in your RequireJS config: 142 | 143 | ... 144 | paths: { 145 | ... 146 | Vue: 'node_modules/vue/dist/vue.min', 147 | 'vue-loader': 'node_modules/requirejs-vue/requirejs-vue', 148 | 'browser-pug': 'mode_modules/browser-pug/browser-pug' 149 | ... 150 | }, 151 | config: { 152 | 'vue-loader': { 153 | pug: 'browser-pug' 154 | } 155 | } 156 | ... 157 | 158 | 159 | 3. Mark template as pug-able in your Vue component: 160 | 161 | ```html 162 | 167 | 177 | ``` 178 | 179 | ***Note: be aware of using this heavily in production may slow down your app initialization due client-side `.pug` rendering*** 180 | 181 | ### Server-side building with r.js 182 | 183 | Plugin supports RequireJS Optimizer. Follow the usual r.js workflow: specify build config in ```build.js``` like: 184 | 185 | ```js 186 | { 187 | baseUrl: './', 188 | name: 'init', 189 | out: './dist.js', 190 | findNestedDependencies: true, 191 | optimize: 'none', 192 | paths: { 193 | Vue: 'node_modules/vue/dist/vue.min', 194 | vue: 'node_modules/requirejs-vue/requirejs-vue', 195 | app: 'your-entry-point' 196 | } 197 | } 198 | ``` 199 | 200 | and then run builder: 201 | 202 | ``` 203 | r.js -o build.js 204 | ``` 205 | 206 | For advanced usage see [demo project](/demo/). 207 | 208 | ## License 209 | 210 | MIT © 2017 vikseriq -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "requirejs-vue", 3 | "description": "An AMD loader for Vue components 🤘🏽", 4 | "main": "requirejs-vue.js", 5 | "authors": [ 6 | "Wiktor Serow " 7 | ], 8 | "license": "MIT", 9 | "keywords": [ 10 | "javascript", 11 | "vuejs", 12 | "requirejs", 13 | "loader", 14 | "vue" 15 | ], 16 | "homepage": "https://github.com/vikseriq/requirejs-vue", 17 | "ignore": [ 18 | "node_modules", 19 | "bower_components" 20 | ], 21 | "dependencies": { 22 | "requirejs": "^2.3.5", 23 | "vue": "^2.5.9" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /demo/README.md: -------------------------------------------------------------------------------- 1 | # requirejs-vue Sample 2 | 3 | This sample demonstrates way to load Vue components with RequireJS 4 | 5 | ## Prepare 6 | 7 | Run ```bower install``` 8 | 9 | This will download necessary libraries into `bower_components`. 10 | 11 | ## Run 12 | 13 | Due to browser's XMLHttpRequest CSRF limitations use a local server to serve files from current directory, 14 | for example with Python built-in module: 15 | 16 | ```bash 17 | python -m SimpleHTTPServer 8008 & open http://localhost:8008/index.html 18 | ``` 19 | 20 | ## Build with r.js 21 | 22 | To create production-ready js bundle we suggest to use [r.js optimizer](http://requirejs.org/docs/optimization.html). 23 | 24 | 0. Install r.js optimizer: 25 | 26 | ```bash 27 | npm install -g requirejs 28 | ``` 29 | 30 | 1. Make `app.dist.js` by calling 31 | 32 | ```bash 33 | r.js -o app.build.js 34 | ``` 35 | 36 | The combined and minified bundle will be generated for standalone usage. 37 | 38 | 2. And then simply open `app.dist.html`. 39 | 40 | Note: *currently Vue-component's styles will omitted during build – use standard css instead*. 41 | -------------------------------------------------------------------------------- /demo/app.build.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | return { 3 | baseUrl: "./lib", 4 | // load config from app main file 5 | mainConfigFile: 'lib/main.js', 6 | // name of initial file - like `data-main` attr 7 | name: "main", 8 | // force include requirejs into bundle 9 | include: ['requirejs'], 10 | // relative path to requirejs src 11 | paths: { 12 | 'requirejs': '../bower_components/requirejs/require' 13 | }, 14 | // strip comments 15 | preserveLicenseComments: false, 16 | // lookup nested - like require component inside component 17 | findNestedDependencies: true, 18 | // output file 19 | out: "app.dist.js" 20 | } 21 | })(); -------------------------------------------------------------------------------- /demo/app.dist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vue SFC Loader Demo - single build 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 |
14 |

This is production-ready app with combined js into one file

15 | 16 | -------------------------------------------------------------------------------- /demo/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "requirejs-vue-demo", 3 | "authors": [ 4 | "vikseriq" 5 | ], 6 | "description": "", 7 | "main": "", 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "bower_components" 14 | ], 15 | "dependencies": { 16 | "vue": "^2.2.0", 17 | "requirejs": "^2.3.0", 18 | "requirejs-vue": "^1.1.5" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vue SFC Loader Demo 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /demo/lib/clock.html: -------------------------------------------------------------------------------- 1 | 2 | 34 | 44 | -------------------------------------------------------------------------------- /demo/lib/component-head.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | -------------------------------------------------------------------------------- /demo/lib/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A sample usage of requirejs-vue 3 | */ 4 | require( 5 | { 6 | paths: { 7 | 'Vue': '../bower_components/vue/dist/vue', 8 | 'vue': '../bower_components/requirejs-vue/requirejs-vue' 9 | }, 10 | config: { 11 | // vue loader configuration 12 | 'vue': { 13 | 'css': 'inject', 14 | 'templateVar': '__template__' 15 | } 16 | } 17 | }, 18 | ['Vue', 'vue!clock.html', 'vue!component-head.vue'], 19 | function(Vue, clock){ 20 | // init whole vue app 21 | // component-head placed automatically because of component's pre-registered tag names will found in app template 22 | var app = new Vue({ 23 | el: '#app' 24 | }); 25 | // create DOM node for clock 26 | clock.$mount(); 27 | // dynamically insert 28 | app.$el.appendChild(clock.$el); 29 | } 30 | ); 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "requirejs-vue", 3 | "version": "1.1.5", 4 | "description": "An AMD loader for Vue components 🤘🏽. Pug 🐶 supported.", 5 | "main": "requirejs-vue.js", 6 | "keywords": [ 7 | "javascript", 8 | "vuejs", 9 | "requirejs", 10 | "loader", 11 | "single file component", 12 | "vue", 13 | "pug", 14 | "jade" 15 | ], 16 | "files": [], 17 | "repository": "https://github.com/vikseriq/requirejs-vue", 18 | "author": "Wiktor Serow ", 19 | "license": "MIT", 20 | "dependencies": { 21 | "requirejs": "^2.3.0", 22 | "vue": "^2.2.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /requirejs-vue.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Vue loader for RequireJS 3 | * 4 | * module config: { 5 | * pug: String requirejs module id for `pug` template parser (usually 'browser-pug') 6 | * css: String|Function css transformation strategy 7 | * templateVar: String template name for closure 8 | * } 9 | * 10 | * @version 1.1.5 11 | * @author vikseriq 12 | * @license MIT 13 | */ 14 | define(['module'], function(module){ 15 | 'use strict'; 16 | 17 | var fetchContent = null, 18 | moduleVersion = '1.1.5', 19 | masterConfig = { 20 | isBuild: false, 21 | currentImport: '' 22 | }, 23 | buildMap = {}; 24 | 25 | if (typeof window !== 'undefined' && window.document){ 26 | // browser-side 27 | if (typeof XMLHttpRequest === 'undefined') 28 | throw new Error('XMLHttpRequest not available'); 29 | 30 | fetchContent = function(url, callback){ 31 | var xhr = new XMLHttpRequest(); 32 | xhr.open('GET', url, true); 33 | xhr.onreadystatechange = function(){ 34 | if (xhr.readyState === 4 && this.status < 400) 35 | callback(xhr.responseText); 36 | }; 37 | xhr.send(); 38 | }; 39 | } else { 40 | // probably server-side 41 | var fs = require.nodeRequire('fs'); 42 | if (!fs || !fs.readFileSync) 43 | throw new Error(module.id + ': Unsupported platform'); 44 | 45 | fetchContent = function(url, callback){ 46 | try { 47 | var file = fs.readFileSync(url, 'utf8'); 48 | // remove BOM 😜 49 | if (file[0] === '\uFEFF'){ 50 | file = file.substring(1); 51 | } 52 | callback(file); 53 | } catch (e) { 54 | throw new Error(module.id + ': Can not load file ' + url); 55 | } 56 | }; 57 | } 58 | 59 | var extractor = { 60 | /** 61 | * Extract content surrounded by tag 62 | */ 63 | _wrapped_content: function(text, tagname, options){ 64 | options = options || {whitespaces: false}; 65 | var start = text.indexOf('<' + tagname); 66 | if (start < 0) 67 | return ''; 68 | start = text.indexOf('>', start) + 1; 69 | var end = text.indexOf('', start); 70 | if (options.lastIndex) 71 | end = text.lastIndexOf(''); 72 | 73 | text = text.substring(start, end); 74 | 75 | if (!options.whitespaces) 76 | text = text.replace(/\n/g, ' ').replace(/\s{2,}/g, ' '); 77 | 78 | if (options.escape) 79 | text = text.replace(/(['\\])/g, '\\$1'); 80 | 81 | return text; 82 | }, 83 | 84 | /** 85 | * Cleanup HTML 86 | */ 87 | cleanup: function(text){ 88 | return text.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*|$/, ''); 89 | }, 90 | 91 | /** 92 | * Vue template extractor 93 | */ 94 | template: function(text){ 95 | var start = text.indexOf('