工程结构如下
dev-serverconst config = require('../config'); const express = require('express'); const path = require('path'); const fs = require('fs'); // const favicon=require('serve-favicon'); const exec = require('child_process').exec; process.env.NODE_ENV = config.dev.env.NODE_ENV; console.log(config) const webpack = require('webpack'); const webpackConfig = require('./webpack.config.dev');webpack(webpackConfig, function(err, stats, errStates) {process.stdout.write(stats.toString({colors: true,modules: false,children: false,chunks: false,chunkModules: false}) + '\n') });//######### const app = express(); // app.use(webpackDevMiddleware(compiler, { // hot:false // options // })); app.get("/", renderHtml); app.get("/:file", renderHtml); // app.use(favicon(path.join(__dirname, '../dist/public', 'favicon.ico'))); app.use(express.static(path.join(__dirname, '../dist')));function renderHtml(req, res) {// res.header("Access-Control-Allow-Origin","*");// res.header("Access-Control-Allow-Headers", "x-csrf-token");// res.header("Access-Control-Allow-Headers", "Access-Token");let fileName = req.params.file;if (!fileName) fileName = "index.html";fileName = fileName.split(".html")[0];fs.readFile(path.join(__dirname, '../src/modules/' + fileName + '/' + fileName + '.html'), function(err, data) {// bodyif (err) {console.log(err);//404:NOT FOUNDres.writeHead(404, { "Content-Type": "text/html" });} else {//200:OKres.writeHead(200, { "Content-Type": "text/html" });res.write(data.toString());}res.end();}); }const server = app.listen(3300, function() {console.log("listening on port 3300") });
pack-betaconst config = require('../config'); const delFiles = require('./utils').delFiles; process.env.NODE_ENV = config.beta.env.NODE_ENV; const exec = require('child_process').exec;const webpack = require('webpack'); const webpackConfig = require('./webpack.config.beta');webpack(webpackConfig,function (err, stats) {console.log(err);process.stdout.write(stats.toString({colors: true,modules: false,children: false,chunks: false,chunkModules: false}) + '\n');// exec("gulp", function (err, str, strerr) {// console.log(str);// }); });
pack-prodconst config = require('../config'); const delFiles = require('./utils').delFiles; process.env.NODE_ENV = config.prod.env.NODE_ENV; const exec = require('child_process').exec;const webpack = require('webpack'); const webpackConfig = require('./webpack.config.prod');//delFiles("../dist/js"); //delFiles("../dist/css"); webpack(webpackConfig,function (err, stats) {console.log(err);process.stdout.write(stats.toString({colors: true,modules: false,children: false,chunks: false,chunkModules: false}) + '\n');// exec("gulp", function (err, str, strerr) {// console.log(str);// }); });
utilsconst path = require('path'); const fs = require('fs'); const htmlWebpackPlugin = require('html-webpack-plugin');module.exports = {delFiles: function (route) {let p = path.resolve(__dirname, route);let files = fs.readdirSync(p);for (let i = 0; i < files.length; i++) {del(p + "/" + files[i])}function del(file) {fs.unlinkSync(file);fs.existsSync(file);}return true;},ergodicFiles:function (dirPath) {let l = [];let p = path.resolve(__dirname, dirPath);fs.readdirSync(p).forEach(function(file,i){l.push(file);// l.push({name:file,path:p}); });return l;},ergodicEntry:function (dirPath) {let l = {};let p = path.resolve(__dirname, dirPath);fs.readdirSync(p).forEach(function(file,i){l[file] = [p+'/'+file+'/'+file+'.js']});return l;},getHTMLList:function (dirPath) {let obj = this.ergodicEntry(dirPath);let extra = this.extraResource();let ha=[];for (let key in obj) {ha.push(new htmlWebpackPlugin({template: 'index.html',filename: key + ".html?[hash]",fileId: key,cache:false,env:process.env.NODE_ENV,time:this.dealTime(new Date(),"yyyy-mm-dd hh:mm","-"),extra:(function () {if(extra[key]){return extra[key];}else{return [];}})(),chunks: ['jquery', 'vue', 'common', key]}))}return ha;},source:function(){let path = "http://cdn2.test.dianjingquan.cn";if(process.env.NODE_ENV === 'production') path = "http://cdn2.test.dianjingquan.cn";return {cropper:'<script src="'+path+'/js/cropper.js"></script>',//截图插件snapSvg:'<script src="'+path+'/js/snap.svg-min.js"></script>',//svg动画swiper:'<script src="'+path+'/js/swiper-3.4.2.jquery.min.js"></script>',//swap动画效果jsEncrypt:'<script src="'+path+'/js/jsencrypt.js"></script>',pageWalkThrough:'<script src="'+path+'/js/jquery.pagewalkthrough.min.js"></script>',jqueryUiWidget:'<script src="'+path+'/js/jquery.ui.widget.js"></script>',jqueryFileUpload:'<script src="'+path+'/js/jquery.fileupload.js"></script>',//jquery图片上传插件qrcode:'<script src="'+path+'/js/qrcode.min.js"></script>',//生成二维码插件jedate:'<script src="'+path+'/jedate/jquery.jedate.min.js"></script>',//日历插件emoji:'<script src="'+path+'/js/emoji.js"></script>',//emoji表情gt:'<script src="'+path+'/js/gt.js"></script>',moxie:'<script src="'+path+'/js/moxie.js"></script>',plupload:'<script src="'+path+'/js/plupload.dev.js"></script>'};},extraResource:function () {let s =this.source();return {index:[s.swiper,s.jsEncrypt],matchDetail:[s.pageWalkThrough,s.jqueryUiWidget,s.jqueryFileUpload,s.qrcode,s.snapSvg],createMatch:[s.cropper,s.jedate],userCenter:[s.cropper,s.emoji],entryList:[s.cropper],login:[s.cropper,s.jsEncrypt,s.gt],personalProfile:[s.cropper,s.gt,s.jsEncrypt,s.moxie,s.plupload],previewAgainst:[s.snapSvg],sample:[s.cropper],share:[s.qrcode],vsAgainst:[s.snapSvg]}},dealTime : function (time, type, o) {let tt = new Date(time);switch (type) {case "yyyy-mm-dd hh:mm":return tt.getFullYear() + o + ((tt.getMonth() + 1) < 10 ? '0' + (tt.getMonth() + 1) : (tt.getMonth() + 1)) + o + (tt.getDate() < 10 ? '0' + tt.getDate() : tt.getDate()) + " " + tt.getHours() + ':' + (tt.getMinutes() < 10 ? '0' + tt.getMinutes() : tt.getMinutes());case 'yyyy-mm-dd':return tt.getFullYear() + o + ((tt.getMonth() + 1) < 10 ? '0' + (tt.getMonth() + 1) : (tt.getMonth() + 1)) + o + (tt.getDate() < 10 ? '0' + tt.getDate() : tt.getDate());case 'mm-dd':if (o) {return tt.getMonth() + 1 + o + tt.getDate();} else {return tt.getMonth() + 1 + "月" + tt.getDate() + "日";}case 'hh:mm':return tt.getHours() + ':' + (tt.getMinutes() < 10 ? '0' + tt.getMinutes() : tt.getMinutes())}} };
webpack.baseconst path = require('path'); const util = require('./utils'); const ExtractTextPlugin = require("extract-text-webpack-plugin"); function resolve (dir) {return path.join(__dirname, '..', dir) } let vueOption = {test: /\.vue$/,loader: 'vue-loader',// options: {// loaders: {// css: ExtractTextPlugin.extract({// fallback: "vue-style-loader",// use: "css-loader"// }),// scss: ExtractTextPlugin.extract({// fallback: "vue-style-loader",// use: "css-loader!sass-loader"// }),// }// } }; if(process.env.NODE_ENV === 'beta' || process.env.NODE_ENV === 'prod'){vueOption = {test: /\.vue$/,loader: 'vue-loader',options: {loaders: {css: ExtractTextPlugin.extract({fallback: "vue-style-loader",use: "css-loader"}),scss: ExtractTextPlugin.extract({fallback: "vue-style-loader",use: "css-loader!sass-loader"}),}}} } module.exports = {entry: Object.assign(util.ergodicEntry('../src/modules'),{jquery : ["jquery"],vue : ["vue"],}),//值可以是字符串、数组或对象, module: {rules: [vueOption,{test: /\.js$/,loader: 'babel-loader',exclude: /node_modules/,query:{}},{test: /\.(png|jpg|gif|svg)$/,loader: 'file-loader',options: {name: 'images/[name].[ext]?[hash]'}},{test: /\.(woff|eot|ttf|otf)$/,loader: 'url-loader',options: {name: '[name].[ext]?[hash]'}},{test: /\.css$/,use: ExtractTextPlugin.extract({fallback: "style-loader",use: "css-loader"})},{test: /\.scss$/,use: ExtractTextPlugin.extract({fallback: "style-loader",use: "css-loader!sass-loader"})},// {// test: /\.(css|scss)$/,// loader: "style-loader!css-loader!!sass-loader",// } ]},resolve: {alias: {'env':(function (env) {if (env === 'beta') return resolve('config/env-beta.js');else if (env === 'prod') return resolve('config/env-prod.js');else return resolve('config/env-dev.js');})(process.env.NODE_ENV),'$':'jquery','vue$': 'vue/dist/vue.esm.js','@': resolve('src'),},extensions: ['.ts', '.js','.vue','.css','.scss']} };
webpack.beta const path = require('path'); const webpack = require('webpack'); const merge = require('webpack-merge'); const baseWebpackConfig = require('./webpack.base'); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin"); const util = require('./utils');module.exports = merge(baseWebpackConfig,{output: {path: path.resolve(__dirname, '../build/beta'),//Webpack结果存储publicPath: '/',//用于在生产模式和开发模式下下更新内嵌到css、html,img文件里的url值filename: 'js/[name]-[hash].js',chunkFilename: './js/[name]-[hash].js'},plugins: [new ExtractTextPlugin("css/[name]-[hash].css"),new CommonsChunkPlugin({name:["common","jquery","vue"],filename:"js/[name]-[hash].js",minChunks:2}),...util.getHTMLList('../src/modules'),new webpack.optimize.UglifyJsPlugin({sourceMap: true,compress: {warnings: false,drop_debugger: true,drop_console: true}}),],devServer: {//webpack-dev-server配置historyApiFallback: true,//不跳转noInfo: true,inline: true//实时刷新 },performance: {hints: false},// compress: {// warnings: false, // 去除warning警告// drop_debugger: true, // 发布时去除debugger语句// drop_console: true // 发布时去除console语句// },// devtool: '#eval-source-map' });// if (process.env.NODE_ENV === 'production') { // module.exports.devtool = '#source-map'; // // http://vue-loader.vuejs.org/en/workflow/production.html // module.exports.plugins = (module.exports.plugins || []).concat([ // new webpack.DefinePlugin({ // 'process.env': { // NODE_ENV: '"production"' // } // }), // new webpack.optimize.UglifyJsPlugin({ // sourceMap: true, // compress: { // warnings: false // } // }), // new webpack.LoaderOptionsPlugin({ // minimize: true // }) // ]) // }
webpack.dev const path = require('path'); const merge = require('webpack-merge'); const webpack = require('webpack'); const baseWebpackConfig = require('./webpack.base'); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const util = require('./utils'); module.exports = merge(baseWebpackConfig,{output: {path: path.resolve(__dirname, '../dist'),//Webpack结果存储publicPath: '../',//用于在生产模式和开发模式下下更新内嵌到css、html,img文件里的url值filename: 'js/[name].js'},plugins: [new ExtractTextPlugin("css/[name].css"),// ...util.getHTMLList('../src/modules'), ],devServer: {//webpack-dev-server配置historyApiFallback: true,//不跳转noInfo: true,// inline: true//实时刷新 },performance: {hints: false},watch:true,watchOptions:{// ignored: [/node_modules/,/dist/] }// devtool: '#eval-source-map' });
webpack.prod const path = require('path'); const merge = require('webpack-merge'); const webpack = require('webpack'); const baseWebpackConfig = require('./webpack.base'); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const util = require('./utils'); module.exports = merge(baseWebpackConfig,{output: {path: path.resolve(__dirname, '../dist'),//Webpack结果存储publicPath: '../',//用于在生产模式和开发模式下下更新内嵌到css、html,img文件里的url值filename: 'js/[name].js'},plugins: [new ExtractTextPlugin("css/[name].css"),// ...util.getHTMLList('../src/modules'), ],devServer: {//webpack-dev-server配置historyApiFallback: true,//不跳转noInfo: true,// inline: true//实时刷新 },performance: {hints: false},watch:true,watchOptions:{// ignored: [/node_modules/,/dist/] }// devtool: '#eval-source-map' });
config 文件夹 index.js// see http://vuejs-templates.github.io/webpack for documentation. const path = require('path');module.exports = {beta: {env: {NODE_ENV:'beta'},},dev: {env: {NODE_ENV:'development'},},prod: {env: {NODE_ENV:'prod'},} };
pack.json {"name": "ees_web","version": "1.0.0","description": "","main": "index.js","scripts": {"dev": "node build_setting/dev-server.js","pack-beta": "node build_setting/pack-beta.js","pack-prod": "node build_setting/pack-prod.js"},"keywords": [],"author": "","license": "ISC","dependencies": {"babel-eslint": "^7.2.3","babel-polyfill": "^6.26.0","babel-preset-es2015": "^6.24.1","babel-preset-stage-0": "^6.24.1","babel-preset-stage-1": "^6.24.1","child_process": "^1.0.2","djq-component": "^1.0.1","echarts": "^3.8.5","es6-promise": "^4.1.1","express": "^4.16.2","extract-text-webpack-plugin": "^3.0.2","gulp": "^3.9.1","gulp-inject": "^4.2.0","gulp-minify": "^1.0.0","gulp-sequence": "^0.4.6","jquery": "^3.2.1","node-sass": "^4.7.2","sass-loader": "^6.0.6","ts-loader": "^2.3.4","vee-validate": "^2.0.0-rc.19","vue": "^2.4.2","vue-cli": "^2.8.2","vue-cropper": "^0.2.5","vue-infinite-loading": "^2.2.1","vuex": "^2.4.0","webpack-hot-middleware": "^2.19.1","webpack-merge": "^4.1.1"},"devDependencies": {"babel-core": "^6.26.0","babel-loader": "^7.1.2","babel-preset-es2015": "^6.24.1","cropper": "^3.1.3","css-loader": "^0.28.7","file-loader": "^0.11.2","style-loader": "^0.18.2","stylus-loader": "^3.0.1","url-loader": "^0.5.9","vue-loader": "^13.0.4","vue-router": "^2.7.0","vue-template-compiler": "^2.4.2","webpack": "^3.10.0","webpack-dev-server": "^2.7.1"} }