工程結構以下 css
dev-server const 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) { // body if (err) { console.log(err); //404:NOT FOUND res.writeHead(404, { "Content-Type": "text/html" }); } else { //200:OK res.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-beta const 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-prod const 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); // }); });
utils const 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.base const 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" } }