Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-9, allow async registering of components #10

Merged
merged 1 commit into from
May 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,23 @@ Vue plugin with conventions for automatically wiring components, pages and route

- Docs will be available at https://kaizendorks.github.io/vue-autowire/.

Use it by cloning the repo and building with `npm run build`.
Use it by cloning the repo and building with `npm run build`.

```
import Vue from 'vue'
import App from './App.vue'
import VueAutowire from './autowire';

Vue.config.productionTip = false

Vue.use(VueAutowire, {
// All .js and .vue files except the ones ending with .async.vue
context: require.context('./', true, /\/(?:[^.]+|(?!\.async\.vue$))(\.js|\.vue)$/),
// All the .async.vue files as async components on their own vue file
asyncContext: require.context('./', true, /async\.vue$/, 'lazy')
})

new Vue({
render: h => h(App),
}).$mount('#app')
```
117 changes: 89 additions & 28 deletions dist/vue-autowire.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,83 +8,144 @@
var _defaults = {
routes: {
enabled: true,
pattern: /\.router.js/
pattern: /\.router.js$/
},
components: {
enabled: false,
enabled: true,
pattern: /\/components\/.*\.vue$/
}
};

/**
* Register ruoter files by loading them with webpack.require and wire up Router instance to Vue
* Load router files
* @param {Vue} Vue VueJS instance
* @param {require} requireInstance
* @param {Object} options
*/
function registerRoutes (Vue, requireInstance, options) {
var routeFiles = requireInstance
function registerRoutes (Vue, options) {
var routeFiles = options.requireContext
.keys()
.filter(function (file) { return file.match(options.routes.pattern); });

return routeFiles.map(function (routeFile) {
var routerConfig = requireInstance(routeFile);
var routerConfig = options.requireContext(routeFile);
return routerConfig.default ? routerConfig.default : routerConfig;
});
}

/**
* Register ruoter files by loading them with webpack.require and wire up Router instance to Vue
* Register components files using Vue.component and requiring the file from the context
* @param {Vue} Vue VueJS instance
* @param {require} requireInstance
* @param {Object} options
*/
function registerComponents (Vue, requireInstance, options) {
var componentsFiles = requireInstance
function registerComponents (Vue, options) {
var componentsFiles = options.requireContext
.keys()
.filter(function (file) { return file.match(options.components.pattern); });

var getFileName = function (name) { return /\/([^\/]*)\.vue$/.exec(name)[1]; };

return componentsFiles.map(function (file) {
var name = getFileName(file);
var vueFile = requireInstance(file);
var component = vueFile.hasOwnProperty('default') ? vueFile.default : vueFile;
return Vue.component(name, component);
var component = options.requireContext(file);
// Unwrap "default" from ES6 module
if (component.hasOwnProperty('default')) { component = component.default; }
Vue.component(name, component);

// Return the registered component
return Vue.component(name);
});
}

/**
@param {Object} options User defined options to be parsed
@returns {Object} * @param {Object} options
* Register components files using Vue.component as async components by setting up a factory function using the requireAsyncContext
* Each of these components will be on its own chunk
* @param {Vue} Vue VueJS instance
* @param {Object} options
*/
function parseOptions (options) {
options = options || {};
function registerAsyncComponents (Vue, options) {
var componentsFiles = options.requireAsyncContext
.keys()
.filter(function (file) { return file.match(options.components.pattern); });

var getFileName = function (name) { return /\/([^\/]*)\.async\.vue$/.exec(name)[1]; };

return componentsFiles.map(function (file) {
var name = getFileName(file);
// Register as async component https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components
Vue.component(
name,
function () { return options.requireAsyncContext(file); }
);

// Return the registered component
return Vue.component(name);
});
}

/**
* Merges user provided options with the library defaults
* @param {Object} userOptions User defined options to be parsed
* @returns {Object}
*/
function parseOptions (userOptions) {
userOptions = userOptions || {};

return {
routes: Object.assign({}, _defaults.routes, options.routes),
components: Object.assign({}, _defaults.components, options.components)
// context and asyncContext are user provided using the require.context API
// which allows a 4th argument to specify the mode in which to load files
// By default this is 'sync', but can be made async as in require.context('./', true, /async\.vue$/, 'lazy')
// See https://github.com/webpack/docs/wiki/context#context-module-api
requireContext: userOptions.context,
requireAsyncContext: userOptions.asyncContext && userOptions.asyncContext.id.includes("lazy") ?
userOptions.asyncContext :
null,

// Async mode is enabled/disabled depending on the last argument provided to require.context
// For example, enable async with: require.context('./', true, /(\.js|\.vue)$/, 'lazy')
// async: requireContext.id.includes("lazy"),

// Merge user-specific options for each of the different asset types
routes: Object.assign({}, _defaults.routes, userOptions.routes),
components: Object.assign({}, _defaults.components, userOptions.components)
};
}

function register (options, context, Vue) {
options = parseOptions(options);
/**
* Register each of the different type of assets if they are enabled by the options
* @param {Object} Vue The Vue API
* @param {Object} userOptions User defined options to be parsed
* @param {require} requireContext webpack require.context instance. https://github.com/webpack/docs/wiki/context#context-module-api
* @returns {Object} The Autowire object with all the assets that were wired
*/
function register (Vue, userOptions) {
var options = parseOptions(userOptions);

// Returned autowiring object with registered elements
var aw = {
routes: [],
components: []
};
if (options.routes.enabled) {
aw.routes = registerRoutes(Vue, context, options);
if (options.routes.enabled && options.requireContext) {
aw.routes.push(registerRoutes(Vue, options));
}
if (options.components.enabled && options.requireContext) {
aw.components.push(registerComponents(Vue, options));
}
if (options.components.enabled) {
aw.components = registerComponents(Vue, context, options);
if (options.components.enabled && options.requireAsyncContext) {
aw.components.push(registerAsyncComponents(Vue, options));
}

return aw;
}

function install (Vue, options) {
Vue.autowire = register(options, options.context, Vue);
/**
* Vue plugin definition. See https://vuejs.org/v2/guide/plugins.html#Writing-a-Plugin
* @param {Object} Vue The Vue API
* @param {Object} userOptions User defined options
* @returns {Object} The Autowire object with all the assets that were wired
*/
function install (Vue, userOptions) {
Vue.autowire = register(Vue, userOptions);
}

module.exports = install;
117 changes: 89 additions & 28 deletions dist/vue-autowire.esm.browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,83 +6,144 @@
const _defaults = {
routes: {
enabled: true,
pattern: /\.router.js/
pattern: /\.router.js$/
},
components: {
enabled: false,
enabled: true,
pattern: /\/components\/.*\.vue$/
}
};

/**
* Register ruoter files by loading them with webpack.require and wire up Router instance to Vue
* Load router files
* @param {Vue} Vue VueJS instance
* @param {require} requireInstance
* @param {Object} options
*/
function registerRoutes (Vue, requireInstance, options) {
const routeFiles = requireInstance
function registerRoutes (Vue, options) {
const routeFiles = options.requireContext
.keys()
.filter(file => file.match(options.routes.pattern));

return routeFiles.map(routeFile => {
const routerConfig = requireInstance(routeFile);
const routerConfig = options.requireContext(routeFile);
return routerConfig.default ? routerConfig.default : routerConfig;
});
}

/**
* Register ruoter files by loading them with webpack.require and wire up Router instance to Vue
* Register components files using Vue.component and requiring the file from the context
* @param {Vue} Vue VueJS instance
* @param {require} requireInstance
* @param {Object} options
*/
function registerComponents (Vue, requireInstance, options) {
const componentsFiles = requireInstance
function registerComponents (Vue, options) {
const componentsFiles = options.requireContext
.keys()
.filter(file => file.match(options.components.pattern));

const getFileName = name => /\/([^\/]*)\.vue$/.exec(name)[1];

return componentsFiles.map(file => {
const name = getFileName(file);
const vueFile = requireInstance(file);
const component = vueFile.hasOwnProperty('default') ? vueFile.default : vueFile;
return Vue.component(name, component);
let component = options.requireContext(file);
// Unwrap "default" from ES6 module
if (component.hasOwnProperty('default')) component = component.default;
Vue.component(name, component);

// Return the registered component
return Vue.component(name);
});
}

/**
@param {Object} options User defined options to be parsed
@returns {Object} * @param {Object} options
* Register components files using Vue.component as async components by setting up a factory function using the requireAsyncContext
* Each of these components will be on its own chunk
* @param {Vue} Vue VueJS instance
* @param {Object} options
*/
function parseOptions (options) {
options = options || {};
function registerAsyncComponents (Vue, options) {
const componentsFiles = options.requireAsyncContext
.keys()
.filter(file => file.match(options.components.pattern));

const getFileName = name => /\/([^\/]*)\.async\.vue$/.exec(name)[1];

return componentsFiles.map(file => {
const name = getFileName(file);
// Register as async component https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components
Vue.component(
name,
() => options.requireAsyncContext(file)
);

// Return the registered component
return Vue.component(name);
});
}

/**
* Merges user provided options with the library defaults
* @param {Object} userOptions User defined options to be parsed
* @returns {Object}
*/
function parseOptions (userOptions) {
userOptions = userOptions || {};

return {
routes: Object.assign({}, _defaults.routes, options.routes),
components: Object.assign({}, _defaults.components, options.components)
// context and asyncContext are user provided using the require.context API
// which allows a 4th argument to specify the mode in which to load files
// By default this is 'sync', but can be made async as in require.context('./', true, /async\.vue$/, 'lazy')
// See https://github.com/webpack/docs/wiki/context#context-module-api
requireContext: userOptions.context,
requireAsyncContext: userOptions.asyncContext && userOptions.asyncContext.id.includes("lazy") ?
userOptions.asyncContext :
null,

// Async mode is enabled/disabled depending on the last argument provided to require.context
// For example, enable async with: require.context('./', true, /(\.js|\.vue)$/, 'lazy')
// async: requireContext.id.includes("lazy"),

// Merge user-specific options for each of the different asset types
routes: Object.assign({}, _defaults.routes, userOptions.routes),
components: Object.assign({}, _defaults.components, userOptions.components)
};
}

function register (options, context, Vue) {
options = parseOptions(options);
/**
* Register each of the different type of assets if they are enabled by the options
* @param {Object} Vue The Vue API
* @param {Object} userOptions User defined options to be parsed
* @param {require} requireContext webpack require.context instance. https://github.com/webpack/docs/wiki/context#context-module-api
* @returns {Object} The Autowire object with all the assets that were wired
*/
function register (Vue, userOptions) {
const options = parseOptions(userOptions);

// Returned autowiring object with registered elements
const aw = {
routes: [],
components: []
};
if (options.routes.enabled) {
aw.routes = registerRoutes(Vue, context, options);
if (options.routes.enabled && options.requireContext) {
aw.routes.push(registerRoutes(Vue, options));
}
if (options.components.enabled && options.requireContext) {
aw.components.push(registerComponents(Vue, options));
}
if (options.components.enabled) {
aw.components = registerComponents(Vue, context, options);
if (options.components.enabled && options.requireAsyncContext) {
aw.components.push(registerAsyncComponents(Vue, options));
}

return aw;
}

function install (Vue, options) {
Vue.autowire = register(options, options.context, Vue);
/**
* Vue plugin definition. See https://vuejs.org/v2/guide/plugins.html#Writing-a-Plugin
* @param {Object} Vue The Vue API
* @param {Object} userOptions User defined options
* @returns {Object} The Autowire object with all the assets that were wired
*/
function install (Vue, userOptions) {
Vue.autowire = register(Vue, userOptions);
}

export default install;
2 changes: 1 addition & 1 deletion dist/vue-autowire.esm.browser.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading