refactor structure

This commit is contained in:
Pooya Parsa 2017-06-16 17:12:45 +04:30
parent 0895b333ec
commit 829ffa634b
41 changed files with 873 additions and 200 deletions

View File

@ -1,9 +1,9 @@
#!/usr/bin/env node
var join = require('path').join
const join = require('path').join
var defaultCommand = 'dev'
var commands = new Set([
const defaultCommand = 'dev'
const commands = new Set([
defaultCommand,
'init',
'build',
@ -19,6 +19,6 @@ if (commands.has(cmd)) {
cmd = defaultCommand
}
var bin = join(__dirname, 'nuxt-' + cmd)
const bin = join(__dirname, 'nuxt-' + cmd)
require(bin)

View File

@ -3,11 +3,13 @@
// Show logs
process.env.DEBUG = 'nuxt:*'
var fs = require('fs')
var parseArgs = require('minimist')
var without = require('lodash').without
var Nuxt = require('../')
var resolve = require('path').resolve
const fs = require('fs')
const parseArgs = require('minimist')
const without = require('lodash').without
const { Nuxt } = require('../')
const resolve = require('path').resolve
const debug = require('debug')('nuxt:build')
debug.color = 2 // Force green color
const argv = parseArgs(process.argv.slice(2), {
alias: {
@ -36,8 +38,8 @@ if (argv.help) {
process.exit(0)
}
var rootDir = resolve(argv._[0] || '.')
var nuxtConfigFile = resolve(rootDir, argv['config-file'])
const rootDir = resolve(argv._[0] || '.')
const nuxtConfigFile = resolve(rootDir, argv['config-file'])
var options = {}
if (fs.existsSync(nuxtConfigFile)) {
@ -59,11 +61,11 @@ if (argv.analyze) {
options.build.analyze = true
}
console.log('[nuxt] Building...') // eslint-disable-line no-console
var nuxt = module.exports = new Nuxt(options)
debug('Building...')
const nuxt = module.exports = new Nuxt(options)
nuxt.ready()
.then(() => {
console.log('[nuxt] Building done') // eslint-disable-line no-console
debug('Building done')
})
.catch((err) => {
console.error(err) // eslint-disable-line no-console

View File

@ -3,17 +3,17 @@
// Show logs
process.env.DEBUG = 'nuxt:*'
var _ = require('lodash')
var debug = require('debug')('nuxt:build')
const _ = require('lodash')
const debug = require('debug')('nuxt:build')
debug.color = 2 // force green color
var fs = require('fs')
var parseArgs = require('minimist')
var Nuxt = require('../')
var chokidar = require('chokidar')
var resolve = require('path').resolve
var without = require('lodash').without
const fs = require('fs')
const parseArgs = require('minimist')
const { Nuxt,Server } = require('../')
const chokidar = require('chokidar')
const resolve = require('path').resolve
const without = require('lodash').without
var argv = parseArgs(process.argv.slice(2), {
const argv = parseArgs(process.argv.slice(2), {
alias: {
h: 'help',
H: 'hostname',
@ -48,8 +48,8 @@ if (argv.help) {
process.exit(0)
}
var rootDir = resolve(argv._[0] || '.')
var nuxtConfigFile = resolve(rootDir, argv['config-file'])
const rootDir = resolve(argv._[0] || '.')
const nuxtConfigFile = resolve(rootDir, argv['config-file'])
var options = {}
if (fs.existsSync(nuxtConfigFile)) {
@ -64,19 +64,19 @@ if (typeof options.rootDir !== 'string') {
// Force development mode: add hot reloading and watching changes
options.dev = true
var nuxt = new Nuxt(options)
var port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
var host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
var server = new Nuxt.Server(nuxt).listen(port, host)
const nuxt = new Nuxt(options)
const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
const server = new Server(nuxt).listen(port, host)
listenOnConfigChanges(nuxt, server)
function listenOnConfigChanges (nuxt, server) {
// Listen on nuxt.config.js changes
var build = _.debounce(() => {
const build = _.debounce(() => {
debug('[nuxt.config.js] changed')
delete require.cache[nuxtConfigFile]
var options = {}
const options = {}
if (fs.existsSync(nuxtConfigFile)) {
try {
options = require(nuxtConfigFile)
@ -88,7 +88,7 @@ function listenOnConfigChanges(nuxt, server) {
nuxt.close()
.then(() => {
debug('Rebuilding the app...')
var nuxt = new Nuxt(options)
const nuxt = new Nuxt(options)
server.nuxt = nuxt
return nuxt.ready()
})

View File

@ -3,12 +3,14 @@
// Show logs
process.env.DEBUG = 'nuxt:*'
var fs = require('fs')
var parseArgs = require('minimist')
var Nuxt = require('../')
var resolve = require('path').resolve
const fs = require('fs')
const parseArgs = require('minimist')
const debug = require('debug')('nuxt:generate')
var argv = parseArgs(process.argv.slice(2), {
const { Nuxt } = require('../')
const resolve = require('path').resolve
const argv = parseArgs(process.argv.slice(2), {
alias: {
h: 'help',
c: 'config-file'
@ -33,8 +35,8 @@ if (argv.help) {
process.exit(0)
}
var rootDir = resolve(argv._[0] || '.')
var nuxtConfigFile = resolve(rootDir, argv['config-file'])
const rootDir = resolve(argv._[0] || '.')
const nuxtConfigFile = resolve(rootDir, argv['config-file'])
var options = {}
if (fs.existsSync(nuxtConfigFile)) {
@ -49,11 +51,11 @@ if (typeof options.rootDir !== 'string') {
options.dev = false // Force production mode (no webpack middleware called)
options.runBuild = true // Force doing production build before init
console.log('[nuxt] Generating...') // eslint-disable-line no-console
var nuxt = module.exports = new Nuxt(options)
debug('Generating...')
const nuxt = module.exports = new Nuxt(options)
nuxt.generate()
.then(() => {
console.log('[nuxt] Generate done') // eslint-disable-line no-console
debug('Generate done')
process.exit(0)
})
.catch((err) => {

View File

@ -1,11 +1,11 @@
#!/usr/bin/env node
var fs = require('fs')
var parseArgs = require('minimist')
var Nuxt = require('../')
var resolve = require('path').resolve
const fs = require('fs')
const parseArgs = require('minimist')
const { Nuxt, Server } = require('../')
const resolve = require('path').resolve
var argv = parseArgs(process.argv.slice(2), {
const argv = parseArgs(process.argv.slice(2), {
alias: {
h: 'help',
H: 'hostname',
@ -40,8 +40,8 @@ if (argv.help) {
process.exit(0)
}
var rootDir = resolve(argv._[0] || '.')
var nuxtConfigFile = resolve(rootDir, argv['config-file'])
const rootDir = resolve(argv._[0] || '.')
const nuxtConfigFile = resolve(rootDir, argv['config-file'])
var options = {}
if (fs.existsSync(nuxtConfigFile)) {
@ -55,9 +55,9 @@ if (typeof options.rootDir !== 'string') {
}
options.dev = false // Force production mode (no webpack middleware called)
var nuxt = new Nuxt(options)
var port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
var host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
new Nuxt.Server(nuxt).listen(port, host)
const nuxt = new Nuxt(options)
const port = argv.port || process.env.PORT || process.env.npm_package_config_nuxt_port
const host = argv.hostname || process.env.HOST || process.env.npm_package_config_nuxt_host
new Server(nuxt).listen(port, host)
module.exports = nuxt

106
build/rollup.config.js Executable file
View File

@ -0,0 +1,106 @@
// Some parts brought from https://github.com/vuejs/vue/blob/dev/build/config.js
const { resolve } = require('path')
const rollupBabel = require('rollup-plugin-babel')
const rollupAlias = require('rollup-plugin-alias')
const rollupCommonJS = require('rollup-plugin-commonjs')
const rollupReplace = require('rollup-plugin-replace')
const rollupResolve = require('rollup-plugin-node-resolve')
const packageJson = require('../package.json')
const dependencies = Object.keys(packageJson.dependencies)
const version = packageJson.version || process.env.VERSION
// -----------------------------
// Banner
// -----------------------------
const banner =
'/*!\n' +
' * Nuxt.js v' + version + '\n' +
' * Released under the MIT License.\n' +
' */'
// -----------------------------
// Aliases
// -----------------------------
const rootDir = resolve(__dirname, '..')
const srcDir = resolve(rootDir, 'src')
const distDir = resolve(rootDir, 'dist')
const aliases = {
core: resolve(srcDir, 'core/index.js'),
builder: resolve(srcDir, 'builder/index.js'),
common: resolve(srcDir, 'common/index.js'),
utils: resolve(srcDir, 'common/utils.js'),
app: resolve(srcDir, 'app'),
}
// -----------------------------
// Builds
// -----------------------------
const builds = {
core: {
entry: resolve(srcDir, 'core/index.js'),
dest: resolve(distDir, 'core.js')
},
builder: {
entry: resolve(srcDir, 'builder/index.js'),
dest: resolve(distDir, 'builder.js')
}
}
// -----------------------------
// Default config
// -----------------------------
function genConfig (opts) {
const config = {
entry: opts.entry,
dest: opts.dest,
external: ['fs', 'path'].concat(dependencies, opts.external),
format: opts.format || 'cjs',
banner: opts.banner || banner,
moduleName: opts.moduleName || 'Nuxt',
sourceMap: true,
plugins: [
rollupAlias(Object.assign({
resolve: ['.js', '.json', '.jsx', '.ts']
}, aliases, opts.alias)),
rollupCommonJS(),
rollupResolve({ jsnext: true }),
rollupBabel(Object.assign({
exclude: 'node_modules/**',
runtimeHelpers: true,
plugins: [
['transform-runtime', { 'helpers': false, 'polyfill': false }],
'transform-async-to-generator',
'array-includes'
],
presets: [
'babel-preset-es2015-rollup'
]
}, opts.babel)),
rollupReplace({
__VERSION__: version
})
].concat(opts.plugins || [])
}
if (opts.env) {
config.plugins.push(rollupReplace({
'process.env.NODE_ENV': JSON.stringify(opts.env)
}))
}
return config
}
if (process.env.TARGET) {
module.exports = genConfig(builds[process.env.TARGET])
} else {
exports.getBuild = name => genConfig(builds[name])
exports.getAllBuilds = () => Object.keys(builds).map(name => genConfig(builds[name]))
}

View File

@ -4,8 +4,24 @@
* Released under the MIT License.
*/
const path = require('path')
process.noDeprecation = true
var Nuxt = require('./dist/nuxt.js')
// Node Source Map Support
// https://github.com/evanw/node-source-map-support
require('source-map-support').install();
module.exports = Nuxt.default ? Nuxt.default : Nuxt
const Core = require('./dist/core.js')
// ------------------------------------------------------------------
// Polyfill Builder into Core
const Builder = require('./dist/builder')
// Use special env flag to specify app dir without modify builder
if (!process.env.NUXT_APP_TEMPALTE_DIR) {
process.env.NUXT_APP_TEMPALTE_DIR = path.resolve(__dirname, 'app')
}
Object.assign(Core, Builder)
// ------------------------------------------------------------------
module.exports = Core.default ? Core.default : Core

View File

@ -46,8 +46,11 @@
"test": "npm run lint && nyc ava --verbose --serial test/",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
"lint": "eslint --ext .js,.vue bin lib pages test/*.js --ignore-pattern lib/app",
"build": "webpack",
"watch": "webpack --watch",
"build": "npm run build:core && npm run build:builder",
"build:core": "rollup -c build/rollup.config.js --environment TARGET:core",
"watch": "npm run build:core -- -w",
"build:builder": "rollup -c build/rollup.config.js --environment TARGET:builder",
"watch:builder": "npm run build:builder -- -w",
"precommit": "npm run lint",
"prepublish": "npm run build",
"postinstall": "opencollective postinstall"
@ -63,6 +66,7 @@
"babel-loader": "^7.0.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-vue-app": "^1.2.0",
"chalk": "^1.1.3",
"chokidar": "^1.7.0",
"compression": "^1.6.2",
"connect": "^3.6.2",
@ -89,6 +93,7 @@
"script-ext-html-webpack-plugin": "^1.8.1",
"serialize-javascript": "^1.3.0",
"serve-static": "^1.12.3",
"source-map-support": "^0.4.15",
"tapable": "^0.2.6",
"tappable": "^1.0.1",
"url-loader": "^0.5.9",
@ -112,6 +117,7 @@
"babel-plugin-array-includes": "^2.0.3",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015-rollup": "^3.0.0",
"babel-preset-stage-2": "^6.24.1",
"codecov": "^2.2.0",
"copy-webpack-plugin": "^4.0.1",
@ -125,10 +131,19 @@
"finalhandler": "^1.0.3",
"jsdom": "^11.0.0",
"json-loader": "^0.5.4",
"lerna": "2.0.0-rc.5",
"nyc": "^11.0.2",
"request": "^2.81.0",
"request-promise-native": "^1.0.4",
"std-mocks": "^1.0.1"
"rollup": "^0.43.0",
"rollup-plugin-alias": "^1.3.1",
"rollup-plugin-babel": "^2.7.1",
"rollup-plugin-commonjs": "^8.0.2",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup-plugin-replace": "^1.1.1",
"rollup-watch": "^4.0.0",
"std-mocks": "^1.0.1",
"uglify-js": "^3.0.17"
},
"collective": {
"type": "opencollective",

View File

@ -8,7 +8,9 @@ import serialize from 'serialize-javascript'
import { join, resolve, basename, dirname } from 'path'
import Tapable from 'tappable'
import MFS from 'memory-fs'
import { r, wp, createRoutes, parallel } from './utils'
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import { r, wp, createRoutes, parallel } from 'utils'
import clientWebpackConfig from './webpack/client.config.js'
import serverWebpackConfig from './webpack/server.config.js'
@ -119,7 +121,9 @@ export default class Builder extends Tapable {
'components/nuxt-loading.vue',
'components/nuxt-child.js',
'components/nuxt-link.js',
'components/nuxt.vue'
'components/nuxt.vue',
'views/app.template.html',
'views/error.html'
]
const templateVars = {
options: this.options,
@ -199,7 +203,9 @@ export default class Builder extends Tapable {
const customFileExists = fs.existsSync(customPath)
return {
src: customFileExists ? customPath : r(__dirname, 'app', file),
src: customFileExists
? customPath
: r(__dirname, '../app', file), // Relative to dist
dst: file,
custom: customFileExists
}
@ -325,7 +331,10 @@ export default class Builder extends Tapable {
// Run after each compile
this.compiler.plugin('done', stats => {
console.log(stats.toString(this.webpackStats)) // eslint-disable-line no-console
// Don't reload failed builds
if (stats.hasErrors() || stats.hasWarnings()) {
return
}
// Reload renderer if available
if (this.nuxt.renderer) {
this.nuxt.renderer.loadResources(mfs)
@ -336,7 +345,7 @@ export default class Builder extends Tapable {
debug('Adding webpack middleware...')
// Create webpack dev middleware
this.webpackDevMiddleware = pify(require('webpack-dev-middleware')(this.compiler.client, {
this.webpackDevMiddleware = pify(webpackDevMiddleware(this.compiler.client, {
publicPath: this.options.build.publicPath,
stats: this.webpackStats,
noInfo: true,
@ -344,7 +353,7 @@ export default class Builder extends Tapable {
watchOptions: this.options.watchers.webpack
}))
this.webpackHotMiddleware = pify(require('webpack-hot-middleware')(this.compiler.client, {
this.webpackHotMiddleware = pify(webpackHotMiddleware(this.compiler.client, {
log: false,
heartbeat: 2500
}))

View File

@ -4,7 +4,7 @@ import _ from 'lodash'
import { resolve, join, dirname, sep } from 'path'
import { minify } from 'html-minifier'
import Tapable from 'tappable'
import { isUrl, promisifyRoute, waitFor, flatRoutes } from './utils'
import { isUrl, promisifyRoute, waitFor, flatRoutes } from 'utils'
const debug = require('debug')('nuxt:generate')
const copy = pify(fs.copy)

7
src/builder/index.js Executable file
View File

@ -0,0 +1,7 @@
import Builder from './builder'
import Generator from './generator'
export default {
Builder,
Generator
}

View File

@ -2,7 +2,7 @@ import ExtractTextPlugin from 'extract-text-webpack-plugin'
import { defaults, cloneDeep } from 'lodash'
import { join, resolve } from 'path'
import webpack from 'webpack'
import { isUrl, urlJoin } from '../utils'
import { isUrl, urlJoin } from 'utils'
import vueLoaderConfig from './vue-loader.config'
import { styleLoader, extractStyles } from './helpers'

15
src/core/index.js Executable file
View File

@ -0,0 +1,15 @@
import Options from './options'
import ModuleContainer from './module'
import Nuxt from './nuxt'
import Renderer from './renderer'
import Server from './server'
import * as Utils from 'utils'
export default {
Options,
ModuleContainer,
Nuxt,
Renderer,
Server,
Utils
}

View File

@ -3,7 +3,7 @@ import fs from 'fs'
import { uniq } from 'lodash'
import hash from 'hash-sum'
import Tapable from 'tappable'
import { chainFn, sequence } from './utils'
import { chainFn, sequence } from 'utils'
const debug = require('debug')('nuxt:module')
@ -102,8 +102,7 @@ export default class ModuleContainer extends Tapable {
if (module.indexOf('~') === 0 || module.indexOf('./') === 0) {
module = path.join(this.options.srcDir, module.substr(1))
}
// eslint-disable-next-line no-eval
module = eval('require')(module)
module = require(module)
}
// Validate module

View File

@ -1,10 +1,9 @@
import Tapable from 'tappable'
import chalk from 'chalk'
import * as Utils from './utils'
import ModuleContainer from './module'
import Renderer from './renderer'
import ModuleContainer from './module-container'
import Server from './server'
import defaults from './defaults'
import Options from './options'
import Core from './index'
const defaultHost = process.env.HOST || process.env.npm_package_config_nuxt_host || 'localhost'
const defaultPort = process.env.PORT || process.env.npm_package_config_nuxt_port || '3000'
@ -13,14 +12,14 @@ export default class Nuxt extends Tapable {
constructor (_options = {}) {
super()
this.options = defaults(_options)
this.options = Options(_options)
this.initialized = false
this.errorHandler = this.errorHandler.bind(this)
// Create instance of core components
this.moduleContainer = new Nuxt.ModuleContainer(this)
this.renderer = new Nuxt.Renderer(this)
this.moduleContainer = new ModuleContainer(this)
this.renderer = new Renderer(this)
// Backward compatibility
this.render = this.renderer.render.bind(this.renderer)
@ -60,8 +59,7 @@ export default class Nuxt extends Tapable {
if (this._builder) {
return this._builder
}
const Builder = require('./builder').default
this._builder = new Builder(this)
this._builder = new Core.Builder(this)
return this._builder
}
@ -69,8 +67,7 @@ export default class Nuxt extends Tapable {
if (this._generator) {
return this._generator
}
const Generator = require('./generator').default
this._generator = new Generator(this)
this._generator = new Core.Generator(this)
return this._generator
}
@ -93,6 +90,7 @@ export default class Nuxt extends Tapable {
process.exit(1)
}
// Both Renderer & Server depend on this method
serverReady ({ host = defaultHost, port = defaultPort } = {}) {
let _host = host === '0.0.0.0' ? 'localhost' : host
@ -113,13 +111,7 @@ export default class Nuxt extends Tapable {
this.initialized = false
if (typeof callback === 'function') {
callback()
await callback()
}
}
}
// Add core components to Nuxt class
Nuxt.Utils = Utils
Nuxt.Renderer = Renderer
Nuxt.ModuleContainer = ModuleContainer
Nuxt.Server = Server

View File

@ -1,9 +1,9 @@
import _ from 'lodash'
import { join, resolve } from 'path'
import { existsSync } from 'fs'
import { isUrl } from './utils'
import { isUrl } from 'utils'
export default function defaults (_options) {
export default function Options (_options) {
// Clone options to prevent unwanted side-effects
const options = Object.assign({}, _options)
@ -30,7 +30,7 @@ export default function defaults (_options) {
options.buildDir = join(options.rootDir, options.buildDir)
// If app.html is defined, set the template path to the user template
options.appTemplatePath = resolve(__dirname, 'views/app.template.html')
options.appTemplatePath = resolve(options.buildDir, 'views/app.template.html')
if (existsSync(join(options.srcDir, 'app.html'))) {
options.appTemplatePath = join(options.srcDir, 'app.html')
}

View File

@ -10,7 +10,7 @@ import _ from 'lodash'
import { resolve, join } from 'path'
import fs from 'fs-extra'
import { createBundleRenderer } from 'vue-server-renderer'
import { getContext, setAnsiColors, encodeHtml } from './utils'
import { getContext, setAnsiColors, encodeHtml } from 'utils'
const debug = require('debug')('nuxt:render')
debug.color = 4 // Force blue color
@ -36,7 +36,7 @@ export default class Renderer extends Tapable {
clientManifest: null,
serverBundle: null,
appTemplate: null,
errorTemplate: parseTemplate(fs.readFileSync(resolve(__dirname, 'views', 'error.html'), 'utf8'))
errorTemplate: '<pre>{{ stack }}</pre>' // Will be loaded on ready
}
// Initialize
@ -70,6 +70,11 @@ export default class Renderer extends Tapable {
this.gzipMiddleware = pify(compression(this.options.render.gzip))
}
const errorTemplatePath = resolve(this.options.buildDir, 'views/error.html')
if (fs.existsSync(errorTemplatePath)) {
this.resources.errorTemplate = parseTemplate(fs.readFileSync(errorTemplatePath, 'utf8'))
}
// Load resources from fs
if (!this.options.dev) {
await this.loadResources()
@ -140,8 +145,10 @@ export default class Renderer extends Tapable {
// Promisify renderToString
this.bundleRenderer.renderToString = pify(this.bundleRenderer.renderToString)
if (!this.options.runBuild) {
this.nuxt.serverReady()
}
}
async render (req, res) {
// Get context

View File

@ -46,8 +46,7 @@ class Server {
if (src.indexOf('~') === 0 || src.indexOf('./') === 0) {
src = path.join(this.nuxt.options.srcDir, src.substr(1))
}
// eslint-disable-next-line no-eval
m = eval('require')(src)
m = require(src)
}
if (m instanceof Function) {
this.app.use(m)

View File

@ -1,59 +0,0 @@
// Until babel-loader 7 is released
process.noDeprecation = true
var nodeExternals = require('webpack-node-externals')
var ProgressBarPlugin = require('progress-bar-webpack-plugin')
var CopyWebpackPlugin = require('copy-webpack-plugin')
var resolve = require('path').resolve
var r = function (p) { return resolve(__dirname, p) }
module.exports = {
target: 'node',
node: {
__dirname: false,
__filename: false
},
devtool: 'source-map',
entry: r('./lib/nuxt.js'),
output: {
path: r('./dist'),
filename: 'nuxt.js',
libraryTarget: 'commonjs2'
},
externals: [
nodeExternals()
],
module: {
rules: [
{
test: /\.json$/,
loader: 'json-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: [
'transform-async-to-generator',
'array-includes',
'transform-runtime'
],
presets: [
['es2015', { modules: false }],
'stage-2'
],
cacheDirectory: true
}
}
]
},
plugins: [
new CopyWebpackPlugin([
{ from: 'lib/app', to: 'app' },
{ from: 'lib/views', to: 'views' }
]),
new ProgressBarPlugin()
]
}

627
yarn.lock

File diff suppressed because it is too large Load Diff