Authored by 陈峰

Merge branch 'feature/hotreload' into 'release/1.0'

Feature/hotreload



See merge request !4
app/build/*
\ No newline at end of file
... ...
... ... @@ -18,6 +18,3 @@ Vue.render({
template: '<App/>',
components: {App}
});
... ...
process.env.NODE_ENV = 'production'
var ora = require('ora')
var rm = require('rimraf')
var path = require('path')
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('./config')
var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
... ...
var path = require('path')
module.exports = {
build: {
env: {
NODE_ENV: '"production"'
},
index: path.resolve(__dirname, './bundle/index.html'),
assetsRoot: path.resolve(__dirname, './bundle'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
bundleAnalyzerReport: process.env.npm_config_report,
},
dev: {
env: {
NODE_ENV: '"dev"'
},
port: 6008,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/Api': 'http://localhost:6007'
},
cssSourceMap: false,
}
}
... ...
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
console.log(event)
if (event.action === 'reload') {
window.location.reload()
}
})
... ...
var config = require('./config')
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf');
// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable
var app = express()
var compiler = webpack(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true,
headers: {
'Access-Control-Allow-Origin': '*'
},
})
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {}
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')({
rewrites: [
{ from: /\.html$/, to: '/index.html' },
{ from: /.*?\.(js)|(css)$/,
to: (context) => {
return context.parsedUrl.pathname;
}
}
]
}))
// serve webpack bundle output
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
var uri = 'http://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})
var server = app.listen(port)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}
... ...
const path = require('path');
const util = {
resolve: (dir) => {
return path.join(__dirname, '../', dir);
}
};
module.exports = util;
var path = require('path')
var config = require('./config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
var autoprefixerLoader = {
loader: 'autoprefixer-loader'
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = [cssLoader, autoprefixerLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
... ...
var utils = require('./utils')
var config = require('./config')
var isProduction = process.env.NODE_ENV === 'production'
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
})
}
... ...
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const util = require('./util');
let utils = require('./utils');
var path = require('path');
let config = require('./config')
let vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
libs: ['vue', 'vue-router'],
view: ['iview'],
app: ['./app.js']
app: './app.js'
},
output: {
path: util.resolve('./build/bundle'),
filename: '[name].[hash:7].js',
chunkFilename: '[name].[hash:7].js',
publicPath: '/'
path: config.build.assetsRoot,
filename: 'js/[name].js',
chunkFilename: 'js/[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
... ... @@ -22,43 +25,14 @@ module.exports = {
vue$: 'vue/dist/vue.esm.js'
},
modules: [
util.resolve(''),
util.resolve('scss'),
util.resolve('config'),
util.resolve('services'),
util.resolve('util'),
resolve(''),
resolve('scss'),
resolve('config'),
resolve('services'),
resolve('util'),
'node_modules'
]
},
devServer: {
host: '0.0.0.0',
port: 6008,
hot: false,
inline: true,
compress: true,
stats: {
colors: true,
children: false,
chunks: false,
assetsSort: 'size',
},
historyApiFallback: {
rewrites: [
{ from: /\.html$/, to: '/index.html' },
{ from: /.*?\.(js)|(css)$/,
to: (context) => {
return context.parsedUrl.pathname;
}
}
]
},
headers: {
'Access-Control-Allow-Origin': '*'
},
proxy: {
'/Api': 'http://localhost:6007'
}
},
module: {
rules: [
{
... ... @@ -71,7 +45,7 @@ module.exports = {
loader: 'url-loader',
options: {
limit: 10000,
name: 'img/[name].[hash:7].[ext]'
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
... ... @@ -79,50 +53,14 @@ module.exports = {
loader: 'url-loader',
options: {
limit: 10000,
name: 'fonts/[name].[ext]'
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: ExtractTextPlugin.extract({
use: 'css-loader!autoprefixer-loader!sass-loader',
fallback: 'vue-style-loader'
})
}
}
}, {
test: /\.css$/,
loader: ExtractTextPlugin.extract({
use: 'css-loader!autoprefixer-loader',
fallback: 'style-loader'
})
}, {
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
use: 'css-loader!autoprefixer-loader!sass-loader',
fallback: 'style-loader'
})
options: vueLoaderConfig
}
]
},
plugins: [
new ExtractTextPlugin('style.[hash:7].css'),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: ['view', 'libs'],
}),
new CleanWebpackPlugin(['*'], {
root: util.resolve('./build/bundle'),
verbose: true,
dry: false
})
]
}
};
... ...
const webpack = require('webpack');
let webpackConfig = require('./webpack.base.conf.js');
let webpack = require('webpack');
var path = require('path');
let config = require('./config')
let utils = require('./utils');
let merge = require('webpack-merge')
let HtmlWebpackPlugin = require('html-webpack-plugin');
let baseConfig = require('./webpack.base.conf.js');
let FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
Object.keys(baseConfig.entry).forEach(function (name) {
baseConfig.entry[name] = ['./build/dev-client'].concat(baseConfig.entry[name])
})
module.exports = merge(baseConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
},
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../index.html',
inject: true
}),
new FriendlyErrorsPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../../node_modules')
) === 0
)
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
}),
]
})
module.exports = webpackConfig;
... ...
const webpack = require('webpack');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
let webpackConfig = require('./webpack.base.conf.js');
let webpack = require('webpack');
var path = require('path');
let config = require('./config')
let utils = require('./utils');
let merge = require('webpack-merge')
let OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
let ExtractTextPlugin = require('extract-text-webpack-plugin');
let HtmlWebpackPlugin = require('html-webpack-plugin');
let baseConfig = require('./webpack.base.conf.js');
var webpackConfig = merge(baseConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true
})
},
devtool: config.build.productionSourceMap ? '#source-map' : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash:7].js'),
chunkFilename: utils.assetsPath('js/[name].[chunkhash:7].js')
},
plugins: [
new webpack.DefinePlugin({
'process.env': config.build.env
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash:7].css')
}),
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
}),
new HtmlWebpackPlugin({
filename: config.build.index,
template: '../index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
}),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../../node_modules')
) === 0
)
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
})
]
});
webpackConfig.plugins.push(new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}));
if (config.build.bundleAnalyzerReport) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
webpackConfig.plugins.push(new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}));
webpackConfig.plugins.push(new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
}));
module.exports = webpackConfig;
module.exports = webpackConfig;
\ No newline at end of file
... ...
export default {
historyMode: 'history',
axiosBaseUrl: '/Api',
... ...
... ... @@ -6,4 +6,4 @@
export default {
name: 'app'
};
</script>
</script>
\ No newline at end of file
... ...
... ... @@ -8,7 +8,3 @@
export default {
};
</script>
<style lang="scss">
</style>
... ...
... ... @@ -24,8 +24,7 @@
<em class="upload-img-tip">尺寸要求150px*150px&nbsp;&nbsp;不大于500KB</em>
</Form-item>
<Form-item label="店铺简介:">
<editor :content="shopData.shopIntro"
@change="updateData">
<editor :content="shopData.shopIntro" @change="updateData" z-index="2">
</editor>
</Form-item>
<Form-item label="品牌-供应商:">
... ...
... ... @@ -2,7 +2,6 @@
* 权限插件
*/
import _ from 'lodash';
import config from 'config';
import axios from 'axios';
import userService from 'user-service';
import iView from 'iview';
... ... @@ -10,7 +9,7 @@ import Rsa from 'rsa';
const plugin = {
updateUser(Vue, user, purviews) {
Vue.$store.set(config.storeKeys.user, Rsa.encrypt(user));
Vue.$store.set(Vue.$config.storeKeys.user, Rsa.encrypt(user));
Vue.prop('user', user);
Vue.prop('isLogin', true);
Vue.prop('purviews', purviews.deep);
... ... @@ -18,7 +17,7 @@ const plugin = {
},
// 权限验证
checkPurview(purviews, to) {
checkPurview() {
return Promise.resolve();
// let pUrl = `/${_.split(to.name, '.').join('/')}`;
... ... @@ -37,7 +36,7 @@ const plugin = {
},
install(Vue) {
Vue.beforeRender((next) => {
let user = Vue.$store.get(config.storeKeys.user);
let user = Vue.$store.get(Vue.$config.storeKeys.user);
let isLogin = Vue.$cookie.get('_isLogin');
if (isLogin && user) {
... ... @@ -87,13 +86,13 @@ const plugin = {
}
};
Vue.switchShop = shopsId => {
Vue.$store.set(config.storeKeys.user, Rsa.encrypt(Vue.$user));
Vue.$store.set(Vue.$config.storeKeys.user, Rsa.encrypt(Vue.$user));
Vue.$cookie.set('_sign', shopsId, {
path: '/'
});
};
Vue.logout = () => {
_.each(config.storeKeys, Vue.$store.remove);
_.each(Vue.$config.storeKeys, Vue.$store.remove);
Vue.prop('user', void 0);
Vue.prop('isLogin', void 0);
Vue.prop('purviews', void 0);
... ...
... ... @@ -91,8 +91,8 @@ const plugin = {
Vue.prop('cookie', cookie);
// 设置axios默认参数
axios.defaults.baseURL = config.axiosBaseUrl;
axios.defaults.responseType = config.axiosResponseType;
axios.defaults.baseURL = Vue.$config.axiosBaseUrl;
axios.defaults.responseType = Vue.$config.axiosResponseType;
}
};
... ...
... ... @@ -6,8 +6,8 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon server/app.js",
"static": "cd app && webpack-dev-server --config ./build/webpack.dev.conf.js",
"build": "cd app && webpack --config ./build/webpack.prod.conf.js",
"static": "cd app && node ./build/dev-server.js",
"build": "cd app && node ./build/build.js",
"lint-js": "eslint --ext .js,.vue -c .eslintrc --cache app server",
"lint-css": "stylelint --syntax scss --extract --config .stylelintrc **/*.vue",
"precommit": "node lint-commit.js"
... ... @@ -40,7 +40,6 @@
"vue-html5-editor": "^1.1.1",
"vue-router": "^2.2.0",
"vue-template-compiler": "^2.2.6",
"webpack-dev-server": "^2.4.2",
"yoho-cookie": "^1.2.0",
"yoho-md5": "^2.0.0",
"yoho-node-lib": "^0.2.18",
... ... @@ -62,6 +61,7 @@
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^1.1.3",
"clean-webpack-plugin": "^0.1.16",
"css-loader": "^0.26.1",
"eslint": "^3.14.1",
... ... @@ -73,14 +73,18 @@
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^2.0.1",
"eslint-plugin-vue": "^2.0.1",
"eventsource-polyfill": "^0.9.6",
"extract-text-webpack-plugin": "^2.0.0",
"file-loader": "^0.10.0",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.28.0",
"husky": "^0.13.3",
"node-sass": "^4.5.2",
"nodemon": "^1.11.0",
"optimize-css-assets-webpack-plugin": "^1.3.0",
"ora": "^1.2.0",
"resolve-url-loader": "^2.0.2",
"rimraf": "^2.6.1",
"sass-loader": "^6.0.3",
"style-loader": "^0.16.1",
"stylelint": "^7.10.1",
... ... @@ -92,6 +96,10 @@
"vue-loader": "^11.1.4",
"vue-style-loader": "^2.0.0",
"webpack": "^2.2.1",
"webpack-dev-middleware": "^1.10.2",
"webpack-dev-server": "^2.4.2",
"webpack-hot-middleware": "^2.18.0",
"webpack-merge": "^4.1.0",
"webpack-px-to-rem": "^0.1.0"
},
"author": "",
... ...