Skip to content

Commit

Permalink
release 2.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoiver committed Nov 26, 2017
1 parent e441e11 commit cb07617
Show file tree
Hide file tree
Showing 308 changed files with 1,440 additions and 14,727 deletions.
4 changes: 2 additions & 2 deletions .fecsignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ coverage
node_modules
dist
bin
_old
core/build/templates
test
core/templates
*.html
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
registry = 'https://registry.npm.taobao.org'
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
lavas
=========

[![npm version](https://badge.fury.io/js/lavas.svg)](https://badge.fury.io/js/lavas)
[![Build Status](https://travis-ci.org/lavas-project/lavas.svg?branch=master)](https://travis-ci.org/lavas-project/lavas)

[![NPM](https://nodei.co/npm/lavas.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/lavas/)

基于 Vue 的 PWA 解决方案,帮助开发者快速搭建 PWA 应用,解决开发 PWA 过程中遇到的各种问题。

[DEMO](https://lavas-project.github.io/lavas-demo/appshell/#/) App Shell 生成的简易 DEMO,建议在手机浏览器中打开
Expand Down Expand Up @@ -28,4 +33,3 @@ $ lavas init


Enjoy it!

2 changes: 1 addition & 1 deletion bin/lavas-cli.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/usr/bin/env node

require('../lib');
require('../dist/cli');
18 changes: 10 additions & 8 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#!/bin/sh

rm -rf ./dist
mkdir dist

cp -R package.json LICENSE README.md bin dist

./node_modules/.bin/babel lib -d dist/lib

echo 'build succeeded'
# rm -rf ./dist
# mkdir dist
#
# cp -R package.json LICENSE README.md bin dist
#
# ./node_modules/.bin/babel lib -d dist/lib
#
# babel src --out-dir lib --copy-files
#
# echo 'build succeeded'
5 changes: 3 additions & 2 deletions lib/build/build.js → cli/build/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

'use strict';

const LavasCore = require('lavas-core');
const LavasCore = require('../../core');

const utils = require('../utils');
const log = require('../utils/log');
Expand All @@ -20,6 +20,7 @@ module.exports = async function () {
let core = new LavasCore(rootDir);

log.info('开始构建...');
await core.build('production');
await core.init(process.env.NODE_ENV || 'production', true);
await core.build();
log.info('构建完成...');
};
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 0 additions & 1 deletion lib/extensions/install.js → cli/extensions/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const ora = require('ora');
const shelljs = require('shelljs');
const fs = require('fs-extra');
const path = require('path');
const glob = require('glob');

const config = require('./config');
const utils = require('../utils');
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion lib/index.js → cli/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const buildCommand = require('./build');
const serverCommand = require('./server');
// const extensionCommand = require('./extensions');

let version = process.env.VERSION || require('../package.json').version;
let version = process.env.VERSION || require('../../package.json').version;

if (!process.argv[2]) {
cp.exec('lavas -h', (err, stdout, stderr) => {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion lib/server/dev.js → cli/server/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

const path = require('path');
const fs = require('fs-extra');
const LavasCore = require('lavas-core');
const LavasCore = require('../../core');
const Koa = require('koa');

const log = require('../utils/log');
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
27 changes: 0 additions & 27 deletions core/README.md

This file was deleted.

245 changes: 245 additions & 0 deletions core/builder/base-builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
/**
* @file BaseBuilder
* @author lavas
*/

import template from 'lodash.template';
import {readFile, pathExists} from 'fs-extra';
import {join} from 'path';

import HtmlWebpackPlugin from 'html-webpack-plugin';
import SkeletonWebpackPlugin from 'vue-skeleton-webpack-plugin';

import {TEMPLATE_HTML} from '../constants';
import {assetsPath} from '../utils/path';
import * as JsonUtil from '../utils/json';
import templateUtil from '../utils/template';

import RouteManager from '../route-manager';
import WebpackConfig from '../webpack';
import {RUMTIME_ITEMS} from '../config-reader';

export default class BaseBuilder {
constructor(core) {
this.core = core;
this.env = core.env;
this.cwd = core.cwd;
this.renderer = core.renderer;

// will be overrided by subclass
this.writeFile = null;

this.init(core.config);
}

/**
* do some initialization stuffs,
* will be called later by rebuild in dev mode
*
* @param {Object} config config
*/
init(config) {
this.config = config;
this.webpackConfig = new WebpackConfig(config, this.env);
this.routeManager = new RouteManager(config, this.env);
this.ssrExists = config.entry.some(e => e.ssr);
this.mpaExists = config.entry.some(e => !e.ssr);
}

/**
* build
*
* @override
*/
build() {
throw new Error('[Lavas] Builder.build() must be overrided.');
}

/**
* close
*
* @override
*/
close() {}

/**
* resolve path relative to ./templates
*
* @param {string} path relative path of file
* @return {string} resolvedPath absolute path of file
*/
templatesPath(path = '/') {
return join(__dirname, '../templates', path);
}

/**
* resolve path relative to ./.lavas
*
* @param {string} path relative path of file
* @return {string} resolvedPath absolute path of file
*/
lavasPath(path = '/') {
return join(this.config.globals.rootDir, './.lavas', path);
}

/**
* write file to /.lavas directory
*
* @param {string} path relative path of file
* @param {string} content content of file
* @return {string} resolvedPath absolute path of file
*/
async writeFileToLavasDir(path, content) {
let resolvedPath = this.lavasPath(path);
await this.writeFile(resolvedPath, content);
return resolvedPath;
}

/**
* write config used in runtime
*/
async writeRuntimeConfig() {
let filteredConfig = JsonUtil.deepPick(this.config, RUMTIME_ITEMS);
await this.writeFileToLavasDir('config.json', JsonUtil.stringify(filteredConfig));
}

/**
* write LavasLink component
*/
async writeLavasLink() {
let lavasLinkTemplate = await readFile(this.templatesPath('LavasLink.js.tmpl'), 'utf8');
await this.writeFileToLavasDir('LavasLink.js', template(lavasLinkTemplate)({
entryConfig: JsonUtil.stringify(this.config.entry)
}));
}

/**
* write an entry file for a skeleton component
*
* @param {string} entryName entryName
* @param {string} skeletonPath used as import
* @return {string} entryPath
*/
async writeSkeletonEntry(entryName, skeletonPath) {
const skeletonEntryTemplate = this.templatesPath('entry-skeleton.tmpl');
return await this.writeFileToLavasDir(
`${entryName}/skeleton.js`,
template(await readFile(skeletonEntryTemplate, 'utf8'))({
skeleton: {
path: skeletonPath
}
})
);
}

/**
* use html webpack plugin
*
* @param {Object} mpaConfig mpaConfig
* @param {string} entryName entryName
* @param {string} baseUrl entry base url
* @param {boolean} watcherEnabled enable watcher
*/
async addHtmlPlugin(mpaConfig, entryName, baseUrl, watcherEnabled) {
// allow user to provide a custom HTML template
let rootDir = this.config.globals.rootDir;
let htmlFilename = `${entryName}.html`;
let customTemplatePath = join(rootDir, `entries/${entryName}/${TEMPLATE_HTML}`);

if (!await pathExists(customTemplatePath)) {
throw new Error(`${TEMPLATE_HTML} required for entry: ${entryName}`);
}

let entryTemplatePath = join(entryName, TEMPLATE_HTML);
let resolvedTemplatePath = await this.writeFileToLavasDir(
entryTemplatePath,
templateUtil.client(await readFile(customTemplatePath, 'utf8'), baseUrl)
);

// add html webpack plugin
mpaConfig.plugins.unshift(new HtmlWebpackPlugin({
filename: htmlFilename,
template: resolvedTemplatePath,
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
favicon: assetsPath('img/icons/favicon.ico'),
chunksSortMode: 'dependency',
cache: false,
chunks: ['manifest', 'vue', 'vendor', entryName],
config: this.config // use config in template
}));

// watch template in development mode
if (watcherEnabled) {
this.addWatcher(customTemplatePath, 'change', async () => {
await this.writeFileToLavasDir(
entryTemplatePath,
templateUtil.client(await readFile(customTemplatePath, 'utf8'), baseUrl)
);
});
}
}

/**
* create a webpack config which will be compiled later
*
* @param {boolean} watcherEnabled enable watcher
* @return {Object} mpaConfig webpack config for MPA
*/
async createMPAConfig(watcherEnabled) {
let rootDir = this.config.globals.rootDir;

// create mpa config based on client config
let mpaConfig = this.webpackConfig.client();
let skeletonEntries = {};

// set context and clear entries
mpaConfig.entry = {};
mpaConfig.name = 'mpaclient';
mpaConfig.context = rootDir;

/**
* for each module needs prerendering, we will:
* 1. add a html-webpack-plugin to output a relative HTML file
* 2. create an entry if a skeleton component is provided
*/
await Promise.all(this.config.entry.map(async entryConfig => {
let {name: entryName, ssr: ssrEnabled, base: baseUrl} = entryConfig;

if (!ssrEnabled) {
// set client entry first
mpaConfig.entry[entryName] = [`./entries/${entryName}/entry-client.js`];

// add html-webpack-plugin
await this.addHtmlPlugin(mpaConfig, entryName, baseUrl, watcherEnabled);

// if skeleton provided, we need to create an entry
let skeletonPath = join(rootDir, `entries/${entryName}/Skeleton.vue`);
let skeletonImportPath = `@/entries/${entryName}/Skeleton.vue`;
if (await pathExists(skeletonPath)) {
let entryPath = await this.writeSkeletonEntry(entryName, skeletonImportPath);
skeletonEntries[entryName] = [entryPath];
}
}
}));

if (Object.keys(skeletonEntries).length) {
// when ssr skeleton, we need to extract css from js
let skeletonConfig = this.webpackConfig.server({cssExtract: true});
// remove vue-ssr-client plugin
skeletonConfig.plugins.pop();
skeletonConfig.entry = skeletonEntries;

// add skeleton plugin
mpaConfig.plugins.push(new SkeletonWebpackPlugin({
webpackConfig: skeletonConfig
}));
}

return mpaConfig;
}
}
Loading

0 comments on commit cb07617

Please sign in to comment.