说明

Vue、Grunt、Webpack的知识请看官方网站

Grunt Tasks:构建、开发调试、打包,命令:grunt build,grunt default,grunt zipall。。。
Webpack:编译Vue、压缩文件
http2:启动http/2服务,命令 node http2.js
server:启动http/1.x服务,命令:node server.js

配置

webpack.config.js

var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js',
chunkFilename: "[id].build.js?[chunkhash]" //vue-router异步加载组件,分包构建的文件命令规则
},
resolveLoader: {
root: path.join(__dirname, 'node_modules')
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue'
},
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
},
{
test: /\.css$/,
loader: 'style!css'
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file'
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file',
query: {
name: '[name].[ext]?[hash]'
}
}
]
},
devtool: '#eval-source-map',
plugins:[]
}

GruntFile.js

var webpack = require("webpack");
var webpackconfig = require("./webpack.config.js");
module.exports = function (grunt) {
// 项目配置
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
clean: {
build: {
src: ["dist/**/*","prod/**/*",'apistore.zip','dist.zip','html.zip'] //清空文件和文件夹
}
},
webpack:{//调用webpack功能进行编译构建
options: webpackconfig,
prod:{//产品构建
devtool: '#source-map',
plugins: webpackconfig.plugins.concat(
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
)
},
dev:{//开发环境构建
devtool: '#eval-source-map',
plugins: webpackconfig.plugins.concat(
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
)
}
},
"webpack-dev-server":{//开发调试,实时编译
options: {
webpack: webpackconfig,
publicPath: webpackconfig.output.publicPath
},
start: {
keepalive: true,
port:8086,
historyApiFallback: true,
noInfo: true,
inline:true,
hot:true,
compress: true,
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
}
},
copy:{//拷贝文件
common:{
files: [
{expand: true, src: ['package.json'], dest: 'prod/'},
{expand: true, src: ['index.html'], dest: 'prod/'},
{expand: true, src: ['dist/**/*'], dest: 'prod/'},
]
},
http2:{
files: [
{expand: true, src: ['http2.js'], dest: 'prod/'},
{expand: true, src: ['ssl/**/*'], dest: 'prod/'}
]
},
http:{
files: [
{expand: true, src: ['http.js'], dest: 'prod/'},
{expand: true, src: ['mine.js'], dest: 'prod/'},
{expand: true, src: ['server.js'], dest: 'prod/'}
]
}
},
zip: {//打zip包
apistore:{
dest:'apistore.zip',src:['prod/**/*']
},
dist:{
dest:'dist.zip',src:['dist/**/*']
},
html:{
dest:'html.zip',src:['dist/**/*.js','dist/**/*.css']
}
},
shell: {//shell命令
options: {
stderr: true
},
dev: {
command: 'npm run dev'
}
}
});
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-zip');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-contrib-copy'); grunt.registerTask('ziph2', ['clean','webpack:prod','copy:common','copy:http2','zip:apistore']);
grunt.registerTask('ziphttp', ['clean','webpack:prod','copy:common','copy:http','zip:apistore']);
grunt.registerTask('zipall', ['clean','webpack:prod','copy:common','copy:http','copy:http2','zip:apistore']);
grunt.registerTask('build-dev', ['clean','webpack:dev']);
grunt.registerTask('build', ['clean','webpack:prod']);
grunt.registerTask('default', ["webpack-dev-server"]);
}

http2.js

var http2 = require("http2"),
url = require("url"),
path = require("path"),
fs = require("fs");
var port = 9443
,indexFile = "/index.html";//端口号和主文件地址 var options = {
key: fs.readFileSync(__dirname + '/ssl/server.key.insecure'),
cert: fs.readFileSync(__dirname + '/ssl/server.crt'),
ca: fs.readFileSync(__dirname + '/ssl/server.csr')
};
function app(request, response) {
var uri = url.parse(request.url).pathname,
filename = path.join(process.cwd(), uri);
fs.exists(filename, function(exists) {
if(!exists) {
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not Found\n");
response.end();
return;
}
if (fs.statSync(filename).isDirectory()) {
fs.exists(filename + indexFile, function(exists){
if(exists) {
fs.readFile(filename + indexFile, "binary", loadFile);
} else {
var files = fs.readdirSync(filename);
var html = '';
var showslash = uri + '/';
for (var i=0; i< files.length; i++){
if(uri == '/') {showslash = '/';} else {showslash = uri + '/';}
html += '<div><a href="' + showslash + files[i] + '">' + files[i] + "</a></div>";
}
response.writeHead(200);
response.write(html);
response.end();
}
});
} else {
fs.readFile(filename, "binary", loadFile);
}
});
function loadFile(err, file) {
if(err) {
response.writeHead(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.end();
return;
}
response.writeHead(200);
response.write(file, "binary");
response.end();
}
}
var server = http2.createServer(options, app);
server.listen(parseInt(port, 10));
console.log("Static file server running at\n => https://localhost:" + port + "/\nCTRL + C to shutdown");

server.js

var resolve = require('path').resolve
, join = require('path').join
, exec = require('child_process').exec
, connect = require('connect')
, stylus = require('stylus')
, jade = require('jade')
, less = require('less-middleware')
, url = require('url')
,compression = require('compression')
,bodyParser = require('body-parser')
,serveStatic = require('serve-static')
,serveIndex = require('serve-index')
,morgan = require('morgan')
, fs = require('fs');
var config = {
auth:undefined,//<user>:<pass> specify basic auth credentials
logs:true,//disable request logging
format:"dev",//fmt specify the log format string
favicon:undefined,//path serve the given favicon
jade:true,//disable jade rendering
less:true,//disable less css rendering
cors:true,//allows cross origin access serving
compress:true,//gzip or deflate the response
exec:undefined,//execute command on each request
hidden:true,//enable hidden file serving
dirs:true,//disable directory serving
icons:true,//disable icons
stylus:true,//disable stylus rendering
port:9449//
}
// path
var path = resolve('.');
// setup the server
var server = connect();
// basic auth
if (config.auth) {
var user = config.auth.split(':')[0];
var pass = config.auth.split(':')[1];
if (!user || !pass) throw new Error('user and pass required');
server.use(connect.basicAuth(user, pass));
}
//
server.use(bodyParser.urlencoded());
// ignore favicon
if(config.favicon){
favicon = require('serve-favicon');
server.use(favicon(__dirname + config.favicon));
}
// logger
if (config.logs) server.use(morgan(config.format));
// convert .styl to .css to trick stylus.middleware
if (config.stylus) {
server.use(function(req, res, next){
req.url = req.url.replace(/\.styl$/, '.css');
next();
});
}
// jade
if (config.jade) {
server.use(function(req, res, next){
if (!req.url.match(/\.jade$/)) return next();
var file = join(path, url.parse(req.url).pathname);
fs.readFile(file, 'utf8', function(err, str){
if (err) return next(err);
try {
var fn = jade.compile(str, { filename: file });
str = fn();
res.setHeader('Content-Type', 'text/html');
res.setHeader('Content-Length', Buffer.byteLength(str));
res.end(str);
} catch (err) {
next(err);
}
});
});
}
// stylus
server.use(stylus.middleware({ src: path }));
// less
if (config.less) {
server.use(less(path));
}
// CORS access for files
if (config.cors) {
server.use(function(req, res, next){
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Accept, x-csrf-token, origin');
if ('OPTIONS' == req.method) return res.end();
next();
});
}
// compression
if (config.compress) {
server.use(compression());
}
// exec command
if (config.exec) {
server.use(function (req, res, next){
exec(program.exec, next);
});
}
// static files
server.use(serveStatic(path, {
maxAge: '1d',
index: ['index.html'],
//setHeaders: setCustomCacheControl,
hidden: config.hidden
}))
// directory serving
if (config.dirs) {
server.use(path,serveIndex(path, {
hidden: config.hidden
, icons: config.icons
}));
}
// start the server
server.listen(config.port, function () {
console.log('\033[90mserving \033[36m%s\033[90m on port \033[96m%d\033[0m', path, config.port);
});

package.json

{
"name": "apistore",
"description": "interferce project",
"private": true,
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --config ./webpack.dev.config.js --inline --hot --port 8086",
"build": "cross-env NODE_ENV=production webpack --config ./webpack.prod.config.js --progress --hide-modules",
"serve": "node server.js",
"http2": "node http2.js"
},
"dependencies": {
"element-ui": "^1.0.0",
"vue": "^2.1.4",
"vue-router":"^2.1.1",
"http2":"^3.3.6",
"http2-static-server":"^1.0.0",
"serve": "^1.4.0",
"path":"0.12.7",
"http":"0.0.0",
"connect": "3.5.0",
"jade": "*",
"less-middleware": "*",
"stylus": "*",
"serve-favicon":"2.3.2",
"compression":"1.6.2",
"body-parser":"1.15.2",
"serve-static":"1.11.1",
"serve-index":"1.8.0",
"morgan":"1.7.0"
},
"devDependencies": {
"babel-core": "^6.0.0",
"babel-loader": "^6.0.0",
"babel-preset-es2015": "^6.13.2",
"cross-env": "^1.0.6",
"css-loader": "^0.23.1",
"file-loader": "^0.8.5",
"style-loader": "^0.13.1",
"vue-loader": "^9.5.1",
"webpack": "2.1.0-beta.22",
"webpack-dev-server": "^2.1.0-beta.0",
"path":"0.12.7",
"serve": "^1.4.0",
"mockjs":"^1.0.1-beta3",
"grunt-contrib-copy":"^1.0.0",
"grunt-zip":"^0.17.1",
"grunt-contrib-imagemin":"^1.0.1",
"grunt-contrib-clean":"^1.0.0",
"grunt-contrib-requirejs":"^1.0.0",
"grunt-webpack":"^1.0.18",
"http2":"^3.3.6",
"http2-static-server":"^1.0.0",
"grunt":"^1.0.1",
"grunt-contrib-watch":"^1.0.0",
"grunt-shell":"^2.1.0"
}
}

Vue+Webpack+Grunt集成的更多相关文章

  1. vue,webpack,node间的关系

    针对在“思否”上看到的关于vue,node,webpack的一些问题及回复,做出如下的整理,给同样不是很清楚的朋友做了解,也供自己学习 原链接:https://segmentfault.com/q/1 ...

  2. vue与TypeScript集成配置最简教程

    https://blog.csdn.net/u014633852/article/details/73706459 https://segmentfault.com/a/119000001187808 ...

  3. 【原创】从零开始搭建Electron+Vue+Webpack项目框架(五)预加载和Electron自动更新

    导航: (一)Electron跑起来(二)从零搭建Vue全家桶+webpack项目框架(三)Electron+Vue+Webpack,联合调试整个项目(四)Electron配置润色(五)预加载及自动更 ...

  4. vue+webpack实践

    最近使用了vue来做SPA应用,记一波学习笔记. 使用vue+webpack实现前端模块化. vuejs——轻量.学习成本低.双向绑定.无dom的操作.组件的形式编写 推荐官方文档 vue.js官方文 ...

  5. windows环境下搭建vue+webpack的开发环境

    前段时间一直在断断续续的看vue的官方文档,后来就慢慢的学习搭建vue的开发环境,已经有将近两周了,每到最后一步的时候就会报错,搞的我好郁闷,搁置了好几天,今天又接着搞vue的开发环境,终于成功了.我 ...

  6. Vue + Webpack + Vue-loader 1

    Vue + Webpack + Vue-loader 原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ Vue-loader 是什么? vue ...

  7. Vue实战Vue-cli项目构建(Vue+webpack系列之一)

    用Vue比较长一段时间了,大大小小做了一些项目,最近想总结一下知识点,出一个Vue+webpack系列,先从项目构建说起--vue-cli. 由于是Vue+webpack这里就不赘述git那些东西,默 ...

  8. 从零开始:一个正式的vue+webpack项目的目录结构是怎么形成的

    如何从零开始一个vue+webpack前端工程工作流的搭建,首先我们先从项目的目录结构入手.一个持续可发展,不断加入新功能,方便后期维护的目录结构究竟是长什么样子的?接下来闰土大叔带你们一起手摸手学起 ...

  9. vue学习:vue+webpack的快速使用指南(新手向)

    一.vue有两种使用方式: 1.下载vue.js <script src="vue.js"></script> 2.使用npm npm install vu ...

随机推荐

  1. IOCP入门

    完成端口(Completion Port)详解 此文讲解最好,也很全面一下其他文章看看就行,也可不看. 单句柄数据,单IO数据 此文讲述比较清晰,可以辅助理解上文. IOCP编程之基本原理:http: ...

  2. [spark案例学习] WEB日志分析

    数据准备 数据下载:美国宇航局肯尼迪航天中心WEB日志 我们先来看看数据:首先将日志加载到RDD,并显示出前20行(默认). import sys import os log_file_path =' ...

  3. zmq学习笔记

    1 zmq_socket(3) Manual Page 1.1 一个socket可连接多个对端socket: 通过使用多个zmq_connect() 1.2 一个socket可绑定到多个地址上接受连接 ...

  4. css样式重置,不建议用通配符

    由于各个浏览器对css样式的默认样式不一致,所以有必要进行样式重置.在网上看到很多建议使用 *{margin:0;padding:0} 重置margin和padding.建议不这样子使用,原因主要是性 ...

  5. 8.4.1 ImageLoader

    ImageLoader 的工作原理(已经不维护了) 在显示图片的时候,它会先在内存中查找:如果没有,就去本地查找:如果还没有,就开一个新的线程去下载这张图片,下载成功会把图片同时缓存到内存和本地. 基 ...

  6. 深入浅出C#中的静态与非静态

    C#语言静态类 vs 普通类  C#语言静态类与普通类的区别有以下几点: 1)C#语言静态类无法实例化而普通类可以: 2)C#语言静态类只能从System.Object基类继承:普通可以继承其它任何非 ...

  7. c++ 时间类型详解 time_t

    Unix时间戳(Unix timestamp),或称Unix时间(Unix time).POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00 ...

  8. 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。

    在调用部分三方库时,由于三方库是基于.NET2.0的.所以在4.0的程序中无法加载.解决方案如下: 在配置文件中添加以下配置 <?xml version="1.0"?> ...

  9. ABP框架详解(五)Navigation

    ABP框架中的Navigation功能用于管理业务系统中所有可用的菜单导航控件,通常在业务系统的首页会有一个全局性的导航菜单,JD商城,天猫,猪八戒网莫不如是.所以为方便起见,Navigation功能 ...

  10. JDBC学习2:为什么要写Class.forName("XXX")?

    Class.forName(String name) 接上一篇JDBC.本来这个内容是放在前面的一篇里面的一起的,后来发现越写越多,想想看就算了,还是单独开一篇文章好了,这样也能写得更加详细点. 上一 ...