Authored by ccbikai(👎🏻🍜)

Merge branch 'feature/webpack2' into release/5.5.1

@@ -151,3 +151,4 @@ public/bundle/* @@ -151,3 +151,4 @@ public/bundle/*
151 nbproject/* 151 nbproject/*
152 .DS_Store 152 .DS_Store
153 .devhost 153 .devhost
  154 +.happypack/*
@@ -15,8 +15,8 @@ @@ -15,8 +15,8 @@
15 "debug": "DEBUG=\"express:*\" nodemon -e js,hbs -i public/ app.js", 15 "debug": "DEBUG=\"express:*\" nodemon -e js,hbs -i public/ app.js",
16 "lint-js": "eslint -c .eslintrc --cache .", 16 "lint-js": "eslint -c .eslintrc --cache .",
17 "lint-css": "stylelint --syntax scss --config .stylelintrc 'public/scss/**/*.css'", 17 "lint-css": "stylelint --syntax scss --config .stylelintrc 'public/scss/**/*.css'",
18 - "lint-vue-js": "eslint -c .eslintrc --cache public/vue/**/*.vue",  
19 - "lint-vue-css": "stylelint --syntax scss --extract --config .stylelintrc public/vue/**/*.vue", 18 + "lint-vue-js": "eslint -c .eslintrc --cache public/vue",
  19 + "lint-vue-css": "stylelint --syntax scss --extract --config .stylelintrc 'public/scss/**/*.vue'",
20 "precommit": "node lint.js" 20 "precommit": "node lint.js"
21 }, 21 },
22 "license": "MIT", 22 "license": "MIT",
@@ -63,9 +63,11 @@ @@ -63,9 +63,11 @@
63 "cssnano": "^3.10.0", 63 "cssnano": "^3.10.0",
64 "eslint": "^3.16.0", 64 "eslint": "^3.16.0",
65 "eslint-config-yoho": "^1.0.1", 65 "eslint-config-yoho": "^1.0.1",
  66 + "eslint-loader": "^1.6.3",
66 "eslint-plugin-html": "^2.0.1", 67 "eslint-plugin-html": "^2.0.1",
67 "extract-text-webpack-plugin": "^2.1.0", 68 "extract-text-webpack-plugin": "^2.1.0",
68 "handlebars-loader": "^1.4.0", 69 "handlebars-loader": "^1.4.0",
  70 + "happypack": "^3.0.3",
69 "husky": "^0.13.1", 71 "husky": "^0.13.1",
70 "nodemon": "^1.11.0", 72 "nodemon": "^1.11.0",
71 "postcss-assets": "^4.0.1", 73 "postcss-assets": "^4.0.1",
@@ -87,6 +89,7 @@ @@ -87,6 +89,7 @@
87 "stylelint": "^7.9.0", 89 "stylelint": "^7.9.0",
88 "stylelint-config-yoho": "^1.2.8", 90 "stylelint-config-yoho": "^1.2.8",
89 "stylelint-processor-html": "^1.0.0", 91 "stylelint-processor-html": "^1.0.0",
  92 + "stylelint-webpack-plugin": "^0.7.0",
90 "vue": "^2.1.10", 93 "vue": "^2.1.10",
91 "vue-loader": "^11.1.4", 94 "vue-loader": "^11.1.4",
92 "vue-template-compiler": "^2.1.10", 95 "vue-template-compiler": "^2.1.10",
@@ -2,16 +2,25 @@ @@ -2,16 +2,25 @@
2 2
3 /** 3 /**
4 * postcss plugins for both dev and pro 4 * postcss plugins for both dev and pro
5 - * @parem et Symbol  
6 */ 5 */
7 -const psprites = require('postcss-sprites'); 6 +
8 const path = require('path'); 7 const path = require('path');
  8 +const precss = require('precss');
  9 +const cssnano = require('cssnano');
  10 +const autoprefixer = require('autoprefixer');
  11 +const postSprites = require('postcss-sprites');
  12 +const postImport = require('postcss-import');
  13 +const postAssets = require('postcss-assets');
  14 +const postCalc = require('postcss-calc');
  15 +const postPxtorem = require('postcss-pxtorem');
  16 +const postUse = require('postcss-use');
  17 +const spritescore = require('postcss-sprites/lib/core');
9 const config = require('../../package.json'); 18 const config = require('../../package.json');
10 const distDir = path.join(__dirname, `../dist/${config.name}/${config.version}`); 19 const distDir = path.join(__dirname, `../dist/${config.name}/${config.version}`);
11 const dist = { 20 const dist = {
12 img: distDir + '/img', 21 img: distDir + '/img',
13 font: distDir + '/font' 22 font: distDir + '/font'
14 -} 23 +};
15 24
16 exports.postcssPlugin = (et) => { 25 exports.postcssPlugin = (et) => {
17 let sprites = { 26 let sprites = {
@@ -19,7 +28,7 @@ exports.postcssPlugin = (et) => { @@ -19,7 +28,7 @@ exports.postcssPlugin = (et) => {
19 padding: 8 28 padding: 8
20 }, 29 },
21 filterBy(file) { 30 filterBy(file) {
22 - // base64 的图片没有 url 过滤掉 31 + // base64 的图片没有 url 过滤掉
23 if (file.url) { 32 if (file.url) {
24 return Promise.resolve(); 33 return Promise.resolve();
25 } 34 }
@@ -38,9 +47,9 @@ exports.postcssPlugin = (et) => { @@ -38,9 +47,9 @@ exports.postcssPlugin = (et) => {
38 return group ? Promise.resolve(group) : Promise.reject('yoho'); 47 return group ? Promise.resolve(group) : Promise.reject('yoho');
39 }, 48 },
40 hooks: { 49 hooks: {
41 - onUpdateRule:function(rule, comment, image){  
42 - image.spriteUrl += ("?t=" + new Date().getTime());  
43 - require('postcss-sprites/lib/core').updateRule(rule, comment, image); 50 + onUpdateRule: function(rule, comment, image) {
  51 + image.spriteUrl += ('?t=' + new Date().getTime());
  52 + spritescore.updateRule(rule, comment, image);
44 } 53 }
45 } 54 }
46 }, 55 },
@@ -74,7 +83,7 @@ exports.postcssPlugin = (et) => { @@ -74,7 +83,7 @@ exports.postcssPlugin = (et) => {
74 } 83 }
75 84
76 plugins = [ 85 plugins = [
77 - require('postcss-import')({ 86 + postImport({
78 path: [path.join(__dirname, '../scss')], 87 path: [path.join(__dirname, '../scss')],
79 resolve(id) { 88 resolve(id) {
80 let name = path.basename(id); 89 let name = path.basename(id);
@@ -85,29 +94,27 @@ exports.postcssPlugin = (et) => { @@ -85,29 +94,27 @@ exports.postcssPlugin = (et) => {
85 return id; 94 return id;
86 } 95 }
87 }), 96 }),
88 - require('precss'),  
89 - (psprites.default || psprites)(sprites),  
90 - require('postcss-assets')(assets),  
91 - require('postcss-calc'),  
92 - require('postcss-pxtorem')({ 97 + precss(),
  98 + postSprites(sprites),
  99 + postAssets(assets),
  100 + postCalc(),
  101 + postPxtorem({
93 rootValue: 40, 102 rootValue: 40,
94 unitPrecision: 5, // 保留5位小数字 103 unitPrecision: 5, // 保留5位小数字
95 minPixelValue: 2, // 小于 2 时,不转换 104 minPixelValue: 2, // 小于 2 时,不转换
96 selectorBlackList: [], // 选择器黑名单,可以使用正则 105 selectorBlackList: [], // 选择器黑名单,可以使用正则
97 propWhiteList: [] // 属性名称为空,表示替换所有属性的值 106 propWhiteList: [] // 属性名称为空,表示替换所有属性的值
98 }), 107 }),
99 - require('autoprefixer')({ 108 + autoprefixer({
100 browsers: ['> 1%'] 109 browsers: ['> 1%']
101 }), 110 }),
102 -  
103 - // 可选  
104 - require('postcss-use')({ 111 + postUse({
105 modules: ['postcss-clearfix', 'postcss-crip', 'postcss-short', 'postcss-center', 'postcss-position'] 112 modules: ['postcss-clearfix', 'postcss-crip', 'postcss-short', 'postcss-center', 'postcss-position']
106 }) 113 })
107 ]; 114 ];
108 115
109 if (et === 'pro') { 116 if (et === 'pro') {
110 - plugins.push(require('cssnano')({ 117 + plugins.push(cssnano({
111 safe: true 118 safe: true
112 })); 119 }));
113 } 120 }
@@ -5,20 +5,23 @@ @@ -5,20 +5,23 @@
5 */ 5 */
6 6
7 'use strict'; 7 'use strict';
8 -  
9 -const webpack = require('webpack');  
10 -const path = require('path');  
11 const _ = require('lodash'); 8 const _ = require('lodash');
  9 +const os = require('os');
  10 +const path = require('path');
  11 +const scss = require('postcss-scss');
12 const shelljs = require('shelljs'); 12 const shelljs = require('shelljs');
  13 +const webpack = require('webpack');
  14 +const HappyPack = require('happypack');
13 const ExtractTextPlugin = require('extract-text-webpack-plugin'); 15 const ExtractTextPlugin = require('extract-text-webpack-plugin');
14 const postcssConfig = require('./postcss.config.js'); 16 const postcssConfig = require('./postcss.config.js');
15 -const scss = require('postcss-scss');  
16 -  
17 const entries = { 17 const entries = {
18 - 'index': path.join(__dirname, '../scss/index.css'),  
19 - 'common': path.join(__dirname, '../scss/common.css'),  
20 - 'feature': path.join(__dirname, '../scss/feature.css') 18 + index: path.join(__dirname, '../scss/index.css'),
  19 + common: path.join(__dirname, '../scss/common.css'),
  20 + feature: path.join(__dirname, '../scss/feature.css')
21 }; 21 };
  22 +const happyThreadPool = HappyPack.ThreadPool({ // eslint-disable-line
  23 + size: os.cpus().length
  24 +});
22 25
23 // 构建各模块子页面JS。生成规则module.page.js 26 // 构建各模块子页面JS。生成规则module.page.js
24 shelljs.ls(path.join(__dirname, '../js/**/*.page.js')).forEach((f) => { 27 shelljs.ls(path.join(__dirname, '../js/**/*.page.js')).forEach((f) => {
@@ -67,7 +70,7 @@ module.exports = (env) => { @@ -67,7 +70,7 @@ module.exports = (env) => {
67 test: /\.js$/, 70 test: /\.js$/,
68 exclude: [/node_modules/], 71 exclude: [/node_modules/],
69 use: [{ 72 use: [{
70 - loader: 'babel-loader' 73 + loader: 'happypack/loader?id=js'
71 }] 74 }]
72 }, { 75 }, {
73 test: /\.css$/, 76 test: /\.css$/,
@@ -89,22 +92,19 @@ module.exports = (env) => { @@ -89,22 +92,19 @@ module.exports = (env) => {
89 }, { 92 }, {
90 test: /\.hbs$/, 93 test: /\.hbs$/,
91 use: [{ 94 use: [{
92 - loader: 'handlebars-loader',  
93 - options: {  
94 - helperDirs: [  
95 - path.join(__dirname, '../js/common/helpers')  
96 - ],  
97 - partialDirs: [  
98 - path.join(__dirname, '../../doraemon/views/partial')  
99 - ]  
100 - } 95 + loader: 'happypack/loader?id=hbs',
101 }] 96 }]
102 }] 97 }]
103 }, 98 },
104 resolve: { 99 resolve: {
105 - modules: ['node_modules', './public/vue', './public/hbs', './public/scss', './public/js'], 100 + modules: [
  101 + path.join(__dirname, '../../node_modules'),
  102 + path.join(__dirname, '../vue'),
  103 + path.join(__dirname, '../hbs'),
  104 + path.join(__dirname, '../scss'),
  105 + path.join(__dirname, '../js')
  106 + ],
106 alias: { 107 alias: {
107 - js: path.join(__dirname, '../js/'),  
108 vue: 'vue/dist/vue.js' 108 vue: 'vue/dist/vue.js'
109 } 109 }
110 }, 110 },
@@ -112,6 +112,26 @@ module.exports = (env) => { @@ -112,6 +112,26 @@ module.exports = (env) => {
112 children: false 112 children: false
113 }, 113 },
114 plugins: [ 114 plugins: [
  115 + new HappyPack({
  116 + id: 'js',
  117 + threadPool: happyThreadPool,
  118 + loaders: ['babel-loader'],
  119 + }),
  120 + new HappyPack({
  121 + id: 'hbs',
  122 + threadPool: happyThreadPool,
  123 + loaders: [{
  124 + loader: 'handlebars-loader',
  125 + options: {
  126 + helperDirs: [
  127 + path.join(__dirname, '../js/common/helpers')
  128 + ],
  129 + partialDirs: [
  130 + path.join(__dirname, '../../doraemon/views/partial')
  131 + ]
  132 + }
  133 + }]
  134 + }),
115 new ExtractTextPlugin('[name].css'), 135 new ExtractTextPlugin('[name].css'),
116 new webpack.optimize.CommonsChunkPlugin({ 136 new webpack.optimize.CommonsChunkPlugin({
117 name: 'libs', 137 name: 'libs',
@@ -123,5 +143,5 @@ module.exports = (env) => { @@ -123,5 +143,5 @@ module.exports = (env) => {
123 'window.jQuery': 'yoho-jquery' 143 'window.jQuery': 'yoho-jquery'
124 }) 144 })
125 ] 145 ]
126 - } 146 + };
127 }; 147 };
@@ -2,20 +2,29 @@ @@ -2,20 +2,29 @@
2 2
3 const path = require('path'); 3 const path = require('path');
4 const webpack = require('webpack'); 4 const webpack = require('webpack');
  5 +const StyleLintPlugin = require('stylelint-webpack-plugin');
5 let baseConfig = require('./webpack.base.config.js'); 6 let baseConfig = require('./webpack.base.config.js');
6 7
7 baseConfig = baseConfig('dev'); 8 baseConfig = baseConfig('dev');
8 -baseConfig.devtool = '#eval'; 9 +baseConfig.devtool = '#inline-source-map';
9 baseConfig.output.publicPath = 'http://localhost:5001/'; 10 baseConfig.output.publicPath = 'http://localhost:5001/';
  11 +baseConfig.module.rules.push({
  12 + enforce: 'pre',
  13 + test: /(\.js|\.vue)$/,
  14 + exclude: /node_modules/,
  15 + loader: 'eslint-loader',
  16 + options: {
  17 + cache: true,
  18 + formatter: require('eslint/lib/formatters/codeframe')
  19 + }
  20 +});
10 baseConfig.devServer = { 21 baseConfig.devServer = {
11 - host: '0.0.0.0', 22 + host: '0.0.0.0',
12 port: 5001, 23 port: 5001,
13 contentBase: [path.join(__dirname, './bundle/'), path.join(__dirname, '../')], 24 contentBase: [path.join(__dirname, './bundle/'), path.join(__dirname, '../')],
14 publicPath: baseConfig.output.publicPath, 25 publicPath: baseConfig.output.publicPath,
15 hot: true, 26 hot: true,
16 inline: true, 27 inline: true,
17 - // quiet: true,  
18 - // clientLogLevel: 'error',  
19 compress: true, 28 compress: true,
20 stats: { 29 stats: {
21 colors: true, 30 colors: true,
@@ -24,9 +33,12 @@ baseConfig.devServer = { @@ -24,9 +33,12 @@ baseConfig.devServer = {
24 headers: { 33 headers: {
25 'Access-Control-Allow-Origin': '*' 34 'Access-Control-Allow-Origin': '*'
26 } 35 }
27 -} 36 +};
28 37
29 baseConfig.plugins.push( 38 baseConfig.plugins.push(
  39 + new StyleLintPlugin({
  40 + files: ['public/scss/**/*.css', 'public/vue/**/*.vue'],
  41 + }),
30 new webpack.HotModuleReplacementPlugin() 42 new webpack.HotModuleReplacementPlugin()
31 ); 43 );
32 44
@@ -11,8 +11,8 @@ let baseConfig = require('./webpack.base.config.js'); @@ -11,8 +11,8 @@ let baseConfig = require('./webpack.base.config.js');
11 11
12 // cope img font 12 // cope img font
13 shelljs.mkdir('-p', distDir); 13 shelljs.mkdir('-p', distDir);
14 -shelljs.cp('-R', path.join(__dirname,'../img/'), distDir);  
15 -shelljs.cp('-R', path.join(__dirname,'../font/'), distDir); 14 +shelljs.cp('-R', path.join(__dirname, '../img/'), distDir);
  15 +shelljs.cp('-R', path.join(__dirname, '../font/'), distDir);
16 16
17 baseConfig = baseConfig('pro'); 17 baseConfig = baseConfig('pro');
18 baseConfig.output.path = distDir; 18 baseConfig.output.path = distDir;