refactor: use more functional programming (#3612)

This commit is contained in:
Alexander Lichter 2018-10-12 23:31:19 +01:00 committed by Pooya Parsa
parent 18802c9a5f
commit 76b10d2d3f
15 changed files with 105 additions and 87 deletions

View File

@ -109,7 +109,7 @@ function mapTransitions(Components, to, from) {
if (from && from.matched.length && from.matched[0].components.default) { if (from && from.matched.length && from.matched[0].components.default) {
const from_transitions = componentTransitions(from.matched[0].components.default) const from_transitions = componentTransitions(from.matched[0].components.default)
Object.keys(from_transitions) Object.keys(from_transitions)
.filter((key) => from_transitions[key] && key.toLowerCase().indexOf('leave') !== -1) .filter((key) => from_transitions[key] && key.toLowerCase().includes('leave'))
.forEach((key) => { transitions[key] = from_transitions[key] }) .forEach((key) => { transitions[key] = from_transitions[key] })
} }

View File

@ -23,6 +23,7 @@ export default {
transitionProps[key] = transition[key] transitionProps[key] = transition[key]
} }
}) })
let listeners = {} let listeners = {}
listenersKeys.forEach((key) => { listenersKeys.forEach((key) => {
if (typeof transition[key] === 'function') { if (typeof transition[key] === 'function') {
@ -30,7 +31,7 @@ export default {
} }
}) })
// Add triggerScroll event on beforeEnter (fix #1376) // Add triggerScroll event on beforeEnter (fix #1376)
let beforeEnter = listeners.beforeEnter const beforeEnter = listeners.beforeEnter
listeners.beforeEnter = (el) => { listeners.beforeEnter = (el) => {
// Ensure to trigger scroll event after calling scrollBehavior // Ensure to trigger scroll event after calling scrollBehavior
window.<%= globals.nuxt %>.$nextTick(() => { window.<%= globals.nuxt %>.$nextTick(() => {

View File

@ -1,18 +1,16 @@
<% if (middleware) { %> <% if (middleware) { %>
let files = require.context('@/<%= dir.middleware %>', false, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/) const files = require.context('@/<%= dir.middleware %>', false, /^\.\/(?!<%= ignorePrefix %>)[^.]+\.(<%= extensions %>)$/)
let filenames = files.keys() const filenames = files.keys()
function getModule (filename) { function getModule (filename) {
let file = files(filename) const file = files(filename)
return file.default return file.default || file
? file.default
: file
} }
let middleware = {} const middleware = {}
// Generate the middleware // Generate the middleware
for (let filename of filenames) { for (const filename of filenames) {
let name = filename.replace(/^\.\//, '').replace(/\.(<%= extensions %>)$/, '') const name = filename.replace(/^\.\//, '').replace(/\.(<%= extensions %>)$/, '')
middleware[name] = getModule(filename) middleware[name] = getModule(filename)
} }

View File

@ -21,7 +21,7 @@ const createNext = (ssrContext) => (opts) => {
} }
opts.query = stringify(opts.query) opts.query = stringify(opts.query)
opts.path = opts.path + (opts.query ? '?' + opts.query : '') opts.path = opts.path + (opts.query ? '?' + opts.query : '')
if (opts.path.indexOf('http') !== 0 && ('<%= router.base %>' !== '/' && opts.path.indexOf('<%= router.base %>') !== 0)) { if (!opts.path.startsWith('http') && ('<%= router.base %>' !== '/' && !opts.path.startsWith('<%= router.base %>'))) {
opts.path = urlJoin('<%= router.base %>', opts.path) opts.path = urlJoin('<%= router.base %>', opts.path)
} }
// Avoid loop redirect // Avoid loop redirect

View File

@ -10,7 +10,7 @@ const filenames = files.keys()
let storeData = {} let storeData = {}
// Check if {dir.store}/index.js exists // Check if {dir.store}/index.js exists
const indexFilename = filenames.find(name => name.includes('./index.')) const indexFilename = filenames.find(filename => filename.includes('./index.'))
if (indexFilename) { if (indexFilename) {
storeData = getModule(indexFilename) storeData = getModule(indexFilename)

View File

@ -496,7 +496,7 @@ function formatUrl (url, query) {
if (index !== -1) { if (index !== -1) {
protocol = url.substring(0, index) protocol = url.substring(0, index)
url = url.substring(index + 3) url = url.substring(index + 3)
} else if (url.indexOf('//') === 0) { } else if (url.startsWith('//')) {
url = url.substring(2) url = url.substring(2)
} }

View File

@ -318,7 +318,6 @@ export default class Builder {
templateVars.router.routes, templateVars.router.routes,
r r
) )
// router.extendRoutes method // router.extendRoutes method
if (typeof this.options.router.extendRoutes === 'function') { if (typeof this.options.router.extendRoutes === 'function') {
// let the user extend the routes // let the user extend the routes
@ -349,7 +348,7 @@ export default class Builder {
templatesFiles = templatesFiles templatesFiles = templatesFiles
.map((file) => { .map((file) => {
// Skip if custom file was already provided in build.templates[] // Skip if custom file was already provided in build.templates[]
if (customTemplateFiles.indexOf(file) !== -1) { if (customTemplateFiles.includes(file)) {
return return
} }
// Allow override templates using a file with same name in ${srcDir}/app // Allow override templates using a file with same name in ${srcDir}/app

View File

@ -1,10 +1,9 @@
import path from 'path' import path from 'path'
import _ from 'lodash'
import htmlMinifier from 'html-minifier' import htmlMinifier from 'html-minifier'
import Chalk from 'chalk' import Chalk from 'chalk'
import fsExtra from 'fs-extra' import fsExtra from 'fs-extra'
import consola from 'consola' import consola from 'consola'
import { flatRoutes, isUrl, promisifyRoute, waitFor } from '../common/utils' import { flatRoutes, isUrl, promisifyRoute, waitFor, isString } from '../common/utils'
export default class Generator { export default class Generator {
constructor(nuxt, builder) { constructor(nuxt, builder) {
@ -187,13 +186,13 @@ export default class Generator {
// Fill routeMap with given generate.routes // Fill routeMap with given generate.routes
generateRoutes.forEach((route) => { generateRoutes.forEach((route) => {
// route is either a string or like { route : '/my_route/1', payload: {} } // route is either a string or like { route : '/my_route/1', payload: {} }
const path = _.isString(route) ? route : route.route const path = isString(route) ? route : route.route
routeMap[path] = { routeMap[path] = {
route: path, route: path,
payload: route.payload || null payload: route.payload || null
} }
}) })
return _.values(routeMap) return Object.values(routeMap)
} }
async generateRoute({ route, payload = {}, errors = [] }) { async generateRoute({ route, payload = {}, errors = [] }) {

View File

@ -76,9 +76,9 @@ export default class WebpackBaseConfig {
'process.mode': JSON.stringify(this.options.mode), 'process.mode': JSON.stringify(this.options.mode),
'process.static': this.isStatic 'process.static': this.isStatic
} }
_.each(this.options.env, (value, key) => { Object.entries(this.options.env).forEach(([key, value]) => {
env['process.env.' + key] = env['process.env.' + key] =
['boolean', 'number'].indexOf(typeof value) !== -1 ['boolean', 'number'].includes(typeof value)
? value ? value
: JSON.stringify(value) : JSON.stringify(value)
}) })
@ -153,15 +153,14 @@ export default class WebpackBaseConfig {
test: /\.jsx?$/, test: /\.jsx?$/,
exclude: (file) => { exclude: (file) => {
// not exclude files outside node_modules // not exclude files outside node_modules
if (/node_modules/.test(file)) { if (!/node_modules/.test(file)) {
for (const module of [/\.vue\.js/].concat(this.options.build.transpile)) { return false
// item in transpile can be string or regex object
if (module.test(file)) {
return false
}
}
return true
} }
// item in transpile can be string or regex object
const modulesToTranspile = [/\.vue\.js/].concat(this.options.build.transpile)
return !modulesToTranspile.some(module => module.test(file))
}, },
use: perfLoader.pool('js', { use: perfLoader.pool('js', {
loader: 'babel-loader', loader: 'babel-loader',

View File

@ -23,7 +23,7 @@ export default class VueSSRClientPlugin {
const asyncFiles = allFiles const asyncFiles = allFiles
.filter(file => isJS(file) || isCSS(file)) .filter(file => isJS(file) || isCSS(file))
.filter(file => initialFiles.indexOf(file) < 0) .filter(file => !initialFiles.includes(file))
const manifest = { const manifest = {
publicPath: stats.publicPath, publicPath: stats.publicPath,

View File

@ -13,7 +13,7 @@ export default class WebpackServerConfig extends BaseConfig {
} }
devtool() { devtool() {
return 'cheap-source-map' return 'cheap-module-inline-source-map'
} }
env() { env() {

View File

@ -1,4 +1,5 @@
import MiniCssExtractPlugin from 'mini-css-extract-plugin' import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import { wrapArray } from '../../../common/utils'
import PostcssConfig from './postcss' import PostcssConfig from './postcss'
export default class StyleLoader { export default class StyleLoader {
@ -19,7 +20,7 @@ export default class StyleLoader {
} }
normalize(loaders) { normalize(loaders) {
loaders = Array.isArray(loaders) ? loaders : [loaders] loaders = wrapArray(loaders)
return loaders.map(loader => (typeof loader === 'string' ? { loader } : loader)) return loaders.map(loader => (typeof loader === 'string' ? { loader } : loader))
} }
@ -28,9 +29,7 @@ export default class StyleLoader {
// style-resources-loader // style-resources-loader
// https://github.com/yenshih/style-resources-loader // https://github.com/yenshih/style-resources-loader
if (extResource) { if (extResource) {
const patterns = Array.isArray(extResource) const patterns = wrapArray(extResource)
? extResource
: [extResource]
return { return {
loader: 'style-resources-loader', loader: 'style-resources-loader',

View File

@ -97,18 +97,14 @@ Options.from = function (_options) {
// Populate modulesDir // Populate modulesDir
options.modulesDir = [] options.modulesDir = []
.concat(options.modulesDir) .concat(options.modulesDir)
.concat(path.join(options.nuxtDir, 'node_modules')) .concat(path.join(options.nuxtDir, 'node_modules')).filter(hasValue)
.filter(hasValue)
.map(dir => path.resolve(options.rootDir, dir)) .map(dir => path.resolve(options.rootDir, dir))
// Sanitize extensions const mandatoryExtensions = ['js', 'mjs']
if (options.extensions.indexOf('js') === -1) {
options.extensions.unshift('js')
}
if (options.extensions.indexOf('mjs') === -1) { options.extensions = mandatoryExtensions
options.extensions.unshift('mjs') .filter(ext => !options.extensions.includes(ext))
} .concat(options.extensions)
// If app.html is defined, set the template path to the user template // If app.html is defined, set the template path to the user template
if (options.appTemplatePath === undefined) { if (options.appTemplatePath === undefined) {

View File

@ -14,6 +14,15 @@ export const waitFor = function waitFor(ms) {
return new Promise(resolve => setTimeout(resolve, ms || 0)) return new Promise(resolve => setTimeout(resolve, ms || 0))
} }
export const isString = function isString(obj) {
return typeof obj === 'string' || obj instanceof String
}
export const startsWithAlias = aliasArray => str => aliasArray.some(c => str.startsWith(c))
export const startsWithSrcAlias = startsWithAlias(['@', '~'])
export const startsWithRootAlias = startsWithAlias(['@@', '~~'])
async function promiseFinally(fn, finalFn) { async function promiseFinally(fn, finalFn) {
let result let result
try { try {
@ -46,7 +55,7 @@ export const urlJoin = function urlJoin() {
} }
export const isUrl = function isUrl(url) { export const isUrl = function isUrl(url) {
return url.indexOf('http') === 0 || url.indexOf('//') === 0 return ['http', '//'].some(str => url.startsWith(str))
} }
export const promisifyRoute = function promisifyRoute(fn, ...args) { export const promisifyRoute = function promisifyRoute(fn, ...args) {
@ -139,11 +148,10 @@ const reqSep = /\//g
const sysSep = _.escapeRegExp(path.sep) const sysSep = _.escapeRegExp(path.sep)
const normalize = string => string.replace(reqSep, sysSep) const normalize = string => string.replace(reqSep, sysSep)
export const r = function r() { export const r = function r(...args) {
const args = Array.prototype.slice.apply(arguments) const lastArg = args[args.length - 1]
const lastArg = _.last(args)
if (lastArg.indexOf('@') === 0 || lastArg.indexOf('~') === 0) { if (startsWithSrcAlias(lastArg)) {
return wp(lastArg) return wp(lastArg)
} }
@ -155,7 +163,7 @@ export const relativeTo = function relativeTo() {
const dir = args.shift() const dir = args.shift()
// Keep webpack inline loader intact // Keep webpack inline loader intact
if (args[0].indexOf('!') !== -1) { if (args[0].includes('!')) {
const loaders = args.shift().split('!') const loaders = args.shift().split('!')
return loaders.concat(relativeTo(dir, loaders.pop(), ...args)).join('!') return loaders.concat(relativeTo(dir, loaders.pop(), ...args)).join('!')
@ -165,7 +173,7 @@ export const relativeTo = function relativeTo() {
const _path = r(...args) const _path = r(...args)
// Check if path is an alias // Check if path is an alias
if (_path.indexOf('@') === 0 || _path.indexOf('~') === 0) { if (startsWithSrcAlias(_path)) {
return _path return _path
} }
@ -180,22 +188,22 @@ export const relativeTo = function relativeTo() {
export const flatRoutes = function flatRoutes(router, _path = '', routes = []) { export const flatRoutes = function flatRoutes(router, _path = '', routes = []) {
router.forEach((r) => { router.forEach((r) => {
if (!r.path.includes(':') && !r.path.includes('*')) { if ([':', '*'].some(c => r.path.includes(c))) {
/* istanbul ignore if */ return
if (r.children) {
if (_path === '' && r.path === '/') {
routes.push('/')
}
flatRoutes(r.children, _path + r.path + '/', routes)
} else {
_path = _path.replace(/^\/+$/, '/')
routes.push(
(r.path === '' && _path[_path.length - 1] === '/'
? _path.slice(0, -1)
: _path) + r.path
)
}
} }
/* istanbul ignore if */
if (r.children) {
if (_path === '' && r.path === '/') {
routes.push('/')
}
return flatRoutes(r.children, _path + r.path + '/', routes)
}
_path = _path.replace(/^\/+$/, '/')
routes.push(
(r.path === '' && _path[_path.length - 1] === '/'
? _path.slice(0, -1)
: _path) + r.path
)
}) })
return routes return routes
} }
@ -214,7 +222,7 @@ function cleanChildrenRoutes(routes, isChild = false) {
}) })
routes.forEach((route) => { routes.forEach((route) => {
route.path = isChild ? route.path.replace('/', '') : route.path route.path = isChild ? route.path.replace('/', '') : route.path
if (route.path.indexOf('?') > -1) { if (route.path.includes('?')) {
const names = route.name.split('-') const names = route.name.split('-')
const paths = route.path.split('/') const paths = route.path.split('/')
if (!isChild) { if (!isChild) {
@ -259,15 +267,15 @@ export const createRoutes = function createRoutes(files, srcDir, pagesDir) {
let parent = routes let parent = routes
keys.forEach((key, i) => { keys.forEach((key, i) => {
// remove underscore only, if its the prefix // remove underscore only, if its the prefix
const sanitizedKey = key.indexOf('_') === 0 const sanitizedKey = key.startsWith('_') ? key.substr(1) : key
? key.replace('_', '')
: key
route.name = route.name route.name = route.name
? route.name + '-' + sanitizedKey ? route.name + '-' + sanitizedKey
: sanitizedKey : sanitizedKey
route.name += key === '_' ? 'all' : '' route.name += key === '_' ? 'all' : ''
route.chunkName = file.replace(/\.(vue|js)$/, '') route.chunkName = file.replace(/\.(vue|js)$/, '')
const child = _.find(parent, { name: route.name }) const child = parent.find(parentRoute => parentRoute.name === route.name)
if (child) { if (child) {
child.children = child.children || [] child.children = child.children || []
parent = child.children parent = child.children
@ -275,13 +283,9 @@ export const createRoutes = function createRoutes(files, srcDir, pagesDir) {
} else if (key === 'index' && i + 1 === keys.length) { } else if (key === 'index' && i + 1 === keys.length) {
route.path += i > 0 ? '' : '/' route.path += i > 0 ? '' : '/'
} else { } else {
route.path += '/' + route.path += '/' + getRoutePathExtension(key)
(key === '_'
? '*' if (key.startsWith('_') && key.length > 1) {
: key.indexOf('_') === 0
? key.replace('_', ':')
: key)
if (key !== '_' && key.indexOf('_') === 0) {
route.path += '?' route.path += '?'
} }
} }
@ -298,12 +302,13 @@ export const createRoutes = function createRoutes(files, srcDir, pagesDir) {
// Order: /static, /index, /:dynamic // Order: /static, /index, /:dynamic
// Match exact route before index: /login before /index/_slug // Match exact route before index: /login before /index/_slug
if (a.path === '/') { if (a.path === '/') {
return /^\/(:|\*)/.test(b.path) ? -1 : 1 return DYNAMIC_ROUTE_REGEX.test(b.path) ? -1 : 1
} }
if (b.path === '/') { if (b.path === '/') {
return /^\/(:|\*)/.test(a.path) ? 1 : -1 return DYNAMIC_ROUTE_REGEX.test(a.path) ? 1 : -1
} }
let i = 0
let i
let res = 0 let res = 0
let y = 0 let y = 0
let z = 0 let z = 0
@ -313,8 +318,8 @@ export const createRoutes = function createRoutes(files, srcDir, pagesDir) {
if (res !== 0) { if (res !== 0) {
break break
} }
y = _a[i] === '*' ? 2 : _a[i].indexOf(':') > -1 ? 1 : 0 y = _a[i] === '*' ? 2 : _a[i].includes(':') ? 1 : 0
z = _b[i] === '*' ? 2 : _b[i].indexOf(':') > -1 ? 1 : 0 z = _b[i] === '*' ? 2 : _b[i].includes(':') ? 1 : 0
res = y - z res = y - z
// If a.length >= b.length // If a.length >= b.length
if (i === _b.length - 1 && res === 0) { if (i === _b.length - 1 && res === 0) {
@ -361,3 +366,25 @@ export const determineGlobals = function determineGlobals(globalName, globals) {
} }
return _globals return _globals
} }
const getRoutePathExtension = (key) => {
if (key === '_') {
return '*'
}
if (key.startsWith('_')) {
return `:${key.substr(1)}`
}
return key
}
const DYNAMIC_ROUTE_REGEX = /^\/(:|\*)/
/**
* Wraps value in array if it is not already an array
*
* @param {any} value
* @return {array}
*/
export const wrapArray = value => Array.isArray(value) ? value : [value]

View File

@ -11,7 +11,7 @@ import esm from 'esm'
import ip from 'ip' import ip from 'ip'
import Options from '../common/options' import Options from '../common/options'
import { sequence } from '../common/utils' import { sequence, startsWithRootAlias, startsWithSrcAlias } from '../common/utils'
import packageJSON from '../../package.json' import packageJSON from '../../package.json'
import ModuleContainer from './module' import ModuleContainer from './module'
@ -254,11 +254,11 @@ export default class Nuxt {
return modulePath return modulePath
} }
if (path.indexOf('@@') === 0 || path.indexOf('~~') === 0) { if (startsWithRootAlias(path)) {
return join(this.options.rootDir, path.substr(2)) return join(this.options.rootDir, path.substr(2))
} }
if (path.indexOf('@') === 0 || path.indexOf('~') === 0) { if (startsWithSrcAlias(path)) {
return join(this.options.srcDir, path.substr(1)) return join(this.options.srcDir, path.substr(1))
} }