webpack做文件合并
使用构建工具非常常用一个功能就是合并js和css文件,gulp和grunt都是编写相应的任务来完成,转到webpack突然懵逼了,简单的项目怎么做文件合并呢?其实只需把多个js文件同时引入到main.js(入口文件)中即可,css借助extract-text-webpack-plugin搞定。
不管是简单的纯展示页面还是复杂的单页或多页面,webpack差不多可以彻底取代gulp、grunt了,利用file、scss、pug、babel等各种loader处理各种需求比grunt那种编写任务型的配置方便太多。
webpack非常智能,多次引入相同模块,最终打包后只会包含一次。如果你不想打包某个模块,在webpack.config.js里配置externals即可。对于css模块,externals是无效的,js里不引入,直接在html里放link就好了,不要陷入webpack的魔障。对于一些老旧的jq插件,可以配置providePlugin或使用expose-loader,用法就自行google了。熟悉了之后,各种新旧项目,大小项目都能用webpack耍的飞起。
// webpack.config.js // ... externals: { 'vue': 'Vue','jquery': 'jQuery',},
webpack-dev-server跨域设置
开发的时候经常有跨域需求,前端跨域方法虽然很多,但是只是为了开发时用用,感觉没一个好用的。利用webpack-dev-server可以轻松解决开发时跨域问题,devServer启动了一个node服务器帮你代理请求,详细配置请看proxy,这个设置是将所有以/api开头的路由映射到xxx.com,target记得带上协议名哦(http://)。pathRewrite就是将/api/a路径重写为/a。当然你也可以配置为/转发请求,这样静态资源也可以在localhost下请求到了。跨域的前提是服务器上配置了'Access-Control-Allow-Origin:*',开发时服务器端一般都设置了。
// webpack.config.js // ... devServer: { port: 8888,historyApiFallback: true,stats: 'minimal',// 输入精简信息 overlay: true,// 将错误显示在html之上 proxy: { '/api': { target: 'http://xxx.com',secure: false,changeOrigin: true,// pathRewrite: {'^/api': ''},} } },
webpack-dev-server热更新失效
自从用了webpack-dev-server,我的f5键长舒一口气,不过有时候碰到webpack-dev-server热更新回失效,一般是配置出了问题。只需在pulugins里添加HotModule插件,devServer不要配置hot:true了,虽然文档里写的是设置hot:true开启热更新,但是我试过配置hot热更新就失效了,不解!
// webpack.config.js // ... plugins: [ new webpack.HotModuleReplacementPlugin(),// 热加载 ]
使用pug(jade)作为vue文件中的html模板
npm安装pug,记住不是pug-loader,也不用配置vue-loader,只需在template标签中指定lang=pug,就可以愉快的使用pug语法了,比起html看起来简洁多了。
<template lang="pug"> header .logo h1 我是头部 </template>
html-webpack-plugin在多页面中的妙用
以前只用webpack写单页引用,index.html就是个空壳,后来也有一些纯展示页面,包含多个html文件,也想用webpack,毕竟各种loader太好用了。这时候就需要好好利用html-webpack-plugin了。直接上一个webpack配置,基于vue-simple的webpack配置做了些修改,同时参考了歪闹大神的webpack多页面教程,利用glod获取文件名,自动生成html-webpack-plugin配置,so geek!利用pug写html,scss写css,作为一个页面仔,也不那么无聊了,效率也是杠杠滴。
let path = require('path'); let webpack = require('webpack'); let ExtractTextPlugin = require('extract-text-webpack-plugin'); let HtmlWebpackPlugin = require('html-webpack-plugin'); let glob = require('glob'); // js名必须与html的fileName对应 let entry = (() => { let obj = {}; getEntry('src/views/pages/*.pug').forEach(fileName => { obj[fileName] = './src/js/' + fileName + '.js'; }); return obj; })(); module.exports = { entry: entry,output: { path: path.resolve(__dirname,'./dist'),publicPath: '/dist/',filename: 'js/[name].js',// chunkFilename: 'js/[name][id].chunk.js',// 公共代码块 },externals: { // 'vue': 'Vue',// 'jquery': 'jQuery',module: { rules: [ { test: /\.vue$/,loader: 'vue-loader',options: { loaders: { scss: ExtractTextPlugin.extract({ fallback: 'vue-style-loader',use: 'css-loader!sass-loader',}),} } },{ test: /\.js$/,loader: 'babel-loader',exclude: /node_modules/ },// 不要使用options配置url-loader webpack会报错 { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,loader: 'url-loader?limit=10000&name=img/[name].[hash:7].[ext]',{ test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,loader: 'file-loader?limit=10000&name=img/[name].[hash:7].[ext]',{ test: /\.scss$/,loader: ExtractTextPlugin.extract({ fallback: 'style-loader',use: 'css-loader!postcss-loader!sass-loader' }) },{ test: /\.css$/,use: 'css-loader!postcss-loader' }) },{ test: /\.html$/,loader: 'html-loader?attrs=img:src img:data-src' },{ test: /\.pug$/,loader: 'pug-loader' },] },resolve: { extensions: ['.js','.vue','.json'],alias: {} },devServer: { port: 8888,// 输入精简信息 overlay: true,// 将错误显示在html之上 proxy: { '/api': { target: 'http://localhost:9999',} } },performance: { hints: false },devtool: '#eval-source-map',plugins: [ new webpack.HotModuleReplacementPlugin(),// 热加载 // new webpack.ProvidePlugin({ // $: 'jquery',// jQuery: 'jquery',// }),new ExtractTextPlugin('css/[name].css'),//单独使用link标签加载css并设置路径,相对于output配置中的publicPath ],}; 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 }) ]); } // 自动生htmlPlugins getEntry('src/views/pages/*.pug').forEach(fileName => { let conf = { filename: fileName + '.html',//生成的html存放路径,相对于path template: 'src/views/pages/' + fileName + '.pug',//html模板路径 inject: true,hash: true,minify: { removeComments: true,minifyJS: true,chunks: [fileName],}; module.exports.plugins.push(new HtmlWebpackPlugin(conf)); }); // 获取文件名函数 function getEntry(viewsPath) { let files = glob.sync(viewsPath); let entries = []; let entry,basename,extname; for (let i = 0; i < files.length; i++) { entry = files[i]; extname = path.extname(entry); // 扩展名 eg: .html basename = path.basename(entry,extname); // eg: index entries.push(basename); } return entries; }
npm pakeage也贴一下吧
{ "name": "vue-admin-front-end","description": "vue-admin","version": "0.0.1","author": "win5do <win5do@qq.com>","private": true,"scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --colors","build": "cross-env NODE_ENV=production webpack --progress --hide-modules" },"dependencies": { "animate.css": "^3.5.2","axios": "^0.16.1","element-ui": "^1.2.9","minireset.css": "^0.0.3","vue": "^2.2.6","vue-router": "^2.5.2","vueditor": "^0.2.4","vuex": "^2.3.1" },"devDependencies": { "babel-core": "^6.24.1","babel-loader": "^7.0.0","babel-preset-latest": "^6.24.1","cross-env": "^4.0.0","css-loader": "^0.28.0","element-theme-default": "^1.2.9","expose-loader": "^0.7.3","extract-text-webpack-plugin": "^2.1.0","file-loader": "^0.11.1","glob": "^7.1.1","html-loader": "^0.4.5","html-webpack-plugin": "^2.28.0","node-sass": "^4.5.2","postcss-loader": "^1.3.3","pug": "^2.0.0-beta.12","pug-loader": "^2.3.0","sass-loader": "^6.0.3","style-loader": "^0.16.1","url-loader": "^0.5.8","vue-loader": "^11.3.4","vue-template-compiler": "^2.2.6","webpack": "^2.4.1","webpack-dev-server": "^2.4.4" } }原文链接:https://www.f2er.com/ajax/161192.html