vue-cli webpack模板项目搭建及打包时路径问题的解决方法


Posted in Javascript onFebruary 26, 2018

这里建议刚学vue的同学第一个小案例不要使用vue-cli进行操作,待对基本的api使用的比较顺手了之后再进行vue-cli的体验比较好。本人是一名后端开发人员,接触前端时间不长,这里有说的不好的地方,还请大家评论建议下。

1. 安装必要的环境准备

首先我们要能够暗转node.js,这个环境。百度搜索node,进入官网根据自己的操作系统进行下载即可。现在的版本都是自带npm的了。所以安装后,环境变量正常情况下会自动配置,开启一个命令行终端,输入node,npm,就可以看到相应的信息。那么说明安装成功。

2. cnpm

由于我们在国内,所以npm的下载路径对我们来说是很慢的,因此我们要使用淘宝提供的cnpm镜像(与maven镜像是一个效果。)百度搜索cnpm,点击进行官网,里面的教程很详细,这里也不会??铝恕?/p>

3. 正式搭建vue-cli

我们首先进行vue-cli的一个下载:

cnpm install -g vue-cli

里面会跟着将webpack一起下载下来,如果没有,那么我们也可以手动自己下载一下webpack就好了,命令相同,只是把vue-cli换成webpack。

下载好之后,进入一个合适的目录,然后输入:

vue-cli webpack vuedemo1

webpack参数是指:我们使用webpack的这套模板

Vuedemo1指:我们在此目录下新建一个名字叫做vuedemo1的目录并将其作为项目的跟目录。

这样,一个空的vue-cli项目就搭建好了

测试一下,输入:

npm run dev

默认开启8080端口,并打开默认浏览器,看到一个熟悉的vue的页面。

4. 配置文件讲解

本身对配置文件理解的并不是特别深刻,这里将自己了解的一些配置含义写出来,共同学习一下。

bulid目录下面的webpack.base.config.js:这里一般是一些基础信息的配置,用过webpack的小伙伴应该都比较熟悉,这里简单讲解一下各个属性:

input:代表入口文件,这里一般指定的是index.html

output:出口文件。

module:这里一般写的的针对各个文件的配置的解析loader。

resolve:这里指其他配置,里面一般有:alias:起别名,例如:

alias: { 
‘vue$': ‘vue/dist/vue.esm.js', 
‘@': resolve(‘src'), 
‘RegForm': ‘@/components/RegForm.vue' //新增 
}

我这里新增一个别名,代表一个路径,这样,以后要引入这个vue文件的时候,直接:

import Regfrom from “RegForm”就可以了。

前面加@,因为默认的配置中将@,取名为resolve('src'),解析了绝对路径。

build下面dev-server.js:

// 检查NodeJS和npm的版本
require('./check-versions')()
// 获取配置
var config = require('../config')
// 如果Node的环境变量中没有设置当前的环境(NODE_ENV),则使用config中的配置作为当前的环境
if (!process.env.NODE_ENV) {
 process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
// 一个可以调用默认软件打开网址、图片、文件等内容的插件
// 这里用它来调用默认浏览器打开dev-server监听的端口,例如:localhost:8080
var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
// 一个express中间件,用于将http请求代理到其他服务器
// 例:localhost:8080/api/xxx --> localhost:3000/api/xxx
// 这里使用该插件可以将前端开发中涉及到的请求代理到API服务器上,方便与服务器对接
var proxyMiddleware = require('http-proxy-middleware')
// 根据 Node 环境来引入相应的 webpack 配置
var webpackConfig = process.env.NODE_ENV === 'testing'
 ? require('./webpack.prod.conf')
 : require('./webpack.dev.conf')
// dev-server 监听的端口,默认为config.dev.port设置的端口,即8080
var port = process.env.PORT || config.dev.port
// 用于判断是否要自动打开浏览器的布尔变量,当配置文件中没有设置自动打开浏览器的时候其值为 false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// 定义 HTTP 代理表,代理到 API 服务器
var proxyTable = config.dev.proxyTable
// 创建1个 express 实例
var app = express()
// 根据webpack配置文件创建Compiler对象
var compiler = webpack(webpackConfig)
// webpack-dev-middleware使用compiler对象来对相应的文件进行编译和绑定
// 编译绑定后将得到的产物存放在内存中而没有写进磁盘
// 将这个中间件交给express使用之后即可访问这些编译后的产品文件
var devMiddleware = require('webpack-dev-middleware')(compiler, {
 publicPath: webpackConfig.output.publicPath,
 quiet: true
})
// webpack-hot-middleware,用于实现热重载功能的中间件
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
 log: () => {}
})
// 当html-webpack-plugin提交之后通过热重载中间件发布重载动作使得页面重载
compiler.plugin('compilation', function (compilation) {
 compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
  hotMiddleware.publish({ action: 'reload' })
  cb()
 })
})
// 将 proxyTable 中的代理请求配置挂在到express服务器上
Object.keys(proxyTable).forEach(function (context) {
 var options = proxyTable[context]
 // 格式化options,例如将'www.example.com'变成{ target: 'www.example.com' }
 if (typeof options === 'string') {
  options = { target: options }
 }
 app.use(proxyMiddleware(options.filter || context, options))
})
// handle fallback for HTML5 history API
// 重定向不存在的URL,常用于SPA
app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
// 使用webpack开发中间件
// 即将webpack编译后输出到内存中的文件资源挂到express服务器上
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
// 将热重载中间件挂在到express服务器上
app.use(hotMiddleware)
// serve pure static assets
// 静态资源的路径
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
// 将静态资源挂到express服务器上
app.use(staticPath, express.static('./static'))
// 应用的地址信息,例如:http://localhost:8080
var uri = 'http://localhost:' + port
// webpack开发中间件合法(valid)之后输出提示语到控制台,表明服务器已启动
devMiddleware.waitUntilValid(function () {
 console.log('> Listening at ' + uri + '\n')
})
// 启动express服务器并监听相应的端口(8080)
module.exports = app.listen(port, function (err) {
 if (err) {
  console.log(err)
  return
 }
 // when env is testing, don't need open it
 // 如果符合自动打开浏览器的条件,则通过opn插件调用系统默认浏览器打开对应的地址uri
 if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
  opn(uri)
 }
})

3.build/webpack.dev.conf.js (npm run dev用到的配置文件 )

var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
// 一个可以合并数组和对象的插件
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
// 一个用于生成HTML文件并自动注入依赖文件(link/script)的webpack插件
var HtmlWebpackPlugin = require('html-webpack-plugin')
// 用于更友好地输出webpack的警告、错误等信息
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
 baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})
// 合并基础的webpack配置
module.exports = merge(baseWebpackConfig, {
 // 配置样式文件的处理规则,使用styleLoaders
 module: {
  rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
 },
 // 配置Source Maps。在开发中使用cheap-module-eval-source-map更快
 devtool: '#cheap-module-eval-source-map',
 // 配置webpack插件
 plugins: [
  new webpack.DefinePlugin({
   'process.env': config.dev.env
  }),
  // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
  new webpack.HotModuleReplacementPlugin(),
  // 后页面中的报错不会阻塞,但是会在编译结束后报错
  new webpack.NoEmitOnErrorsPlugin(),
  // https://github.com/ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
   filename: 'index.html',
   template: 'index.html',
   inject: true
  }),
  new FriendlyErrorsPlugin()
 ]
})

4.build/build.js

// https://github.com/shelljs/shelljs
// 检查NodeJS和npm的版本
require('./check-versions')()
process.env.NODE_ENV = 'production'
// Elegant terminal spinner
var ora = require('ora')
var path = require('path')
// 用于在控制台输出带颜色字体的插件
var chalk = require('chalk')
// 执行Unix命令行的插件
var shell = require('shelljs')
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...')
spinner.start() // 开启loading动画
// 输出文件的目标文件夹
var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
// 递归删除旧的目标文件夹
shell.rm('-rf', assetsPath)
// 重新创建文件夹 
shell.mkdir('-p', assetsPath)
shell.config.silent = true
// 将static文件夹复制到输出的目标文件夹
shell.cp('-R', 'static/*', assetsPath)
shell.config.silent = false
// webpack编译
webpack(webpackConfig, function (err, stats) {
 spinner.stop() // 停止loading动画
 if (err) throw err
 // 没有出错则输出相关信息
 process.stdout.write(stats.toString({
  colors: true,
  modules: false,
  children: false,
  chunks: false,
  chunkModules: false
 }) + '\n\n')
 console.log(chalk.cyan(' Build complete.\n'))
 console.log(chalk.yellow(
  ' Tip: built files are meant to be served over an HTTP server.\n' +
  ' Opening index.html over file:// won\'t work.\n'
 ))
})

5.build/webpack.prod.conf.js (npm run build用到的配置文件)

var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')
// 用于从webpack生成的bundle中提取文本到特定文件中的插件
// 可以抽取出css,js文件将其与webpack输出的bundle分离
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var env = process.env.NODE_ENV === 'testing'
 ? require('../config/test.env')
 : config.build.env
// 合并基础的webpack配置
var webpackConfig = merge(baseWebpackConfig, {
 module: {
  rules: utils.styleLoaders({
   sourceMap: config.build.productionSourceMap,
   extract: true
  })
 },
 devtool: config.build.productionSourceMap ? '#source-map' : false,
 // 配置webpack的输出
 output: {
  // 编译输出目录
  path: config.build.assetsRoot,
  // 编译输出文件名格式
  filename: utils.assetsPath('js/[name].[chunkhash].js'),
  // 没有指定输出名的文件输出的文件名格式
  chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
 },
 // 配置webpack插件
 plugins: [
  // http://vuejs.github.io/vue-loader/en/workflow/production.html
  new webpack.DefinePlugin({
   'process.env': env
  }),
  // 丑化压缩代码
  new webpack.optimize.UglifyJsPlugin({
   compress: {
    warnings: false
   },
   sourceMap: true
  }),
  // 抽离css文件
  new ExtractTextPlugin({
   filename: utils.assetsPath('css/[name].[contenthash].css')
  }),
  // generate dist index.html with correct asset hash for caching.
  // you can customize output by editing /index.html
  // see https://github.com/ampedandwired/html-webpack-plugin
  new HtmlWebpackPlugin({
   filename: process.env.NODE_ENV === 'testing'
    ? 'index.html'
    : config.build.index,
   template: 'index.html',
   inject: true,
   minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: true
    // more options:
    // https://github.com/kangax/html-minifier#options-quick-reference
   },
   // necessary to consistently work with multiple chunks via CommonsChunkPlugin
   chunksSortMode: 'dependency'
  }),
  // split vendor js into its own file
  new webpack.optimize.CommonsChunkPlugin({
   name: 'vendor',
   minChunks: function (module, count) {
    // any required modules inside node_modules are extracted to vendor
    return (
     module.resource &&
     /\.js$/.test(module.resource) &&
     module.resource.indexOf(
      path.join(__dirname, '../node_modules')
     ) === 0
    )
   }
  }),
  // extract webpack runtime and module manifest to its own file in order to
  // prevent vendor hash from being updated whenever app bundle is updated
  new webpack.optimize.CommonsChunkPlugin({
   name: 'manifest',
   chunks: ['vendor']
  })
 ]
})
// gzip模式下需要引入compression插件进行压缩
if (config.build.productionGzip) {
 var CompressionWebpackPlugin = require('compression-webpack-plugin')
 webpackConfig.plugins.push(
  new CompressionWebpackPlugin({
   asset: '[path].gz[query]',
   algorithm: 'gzip',
   test: new RegExp(
    '\\.(' +
    config.build.productionGzipExtensions.join('|') +
    ')$'
   ),
   threshold: 10240,
   minRatio: 0.8
  })
 )
}
if (config.build.bundleAnalyzerReport) {
 var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
 webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

6.config/index.js

// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
 // 构建产品时使用的配置
 build: {
  // webpack的编译环境
  env: require('./prod.env'),
  // 编译输入的index.html文件
  index: path.resolve(__dirname, '../dist/index.html'),
  // webpack输出的目标文件夹路径
  assetsRoot: path.resolve(__dirname, '../dist'),
  // webpack编译输出的二级文件夹
  assetsSubDirectory: 'static',
  // webpack编译输出的发布路径
  assetsPublicPath: '/',
  // 使用SourceMap
  productionSourceMap: true,
  // Gzip off by default as many popular static hosts such as
  // Surge or Netlify already gzip all static assets for you.
  // Before setting to `true`, make sure to:
  // npm install --save-dev compression-webpack-plugin
  // 默认不打开开启gzip模式
  productionGzip: false,
  // gzip模式下需要压缩的文件的扩展名
  productionGzipExtensions: ['js', 'css'],
  // Run the build command with an extra argument to
  // View the bundle analyzer report after build finishes:
  // `npm run build --report`
  // Set to `true` or `false` to always turn it on or off
  bundleAnalyzerReport: process.env.npm_config_report
 },
 // 开发过程中使用的配置
 dev: {
  // webpack的编译环境
  env: require('./dev.env'),
  // dev-server监听的端口
  port: 8080,
  // 启动dev-server之后自动打开浏览器
  autoOpenBrowser: true,
  // webpack编译输出的二级文件夹
  assetsSubDirectory: 'static',
  // webpack编译输出的发布路径
  assetsPublicPath: '/',
  // 请求代理表,在这里可以配置特定的请求代理到对应的API接口
  // 例如将'/api/xxx'代理到'www.example.com/api/xxx'
  proxyTable: {},
  // CSS Sourcemaps off by default because relative paths are "buggy"
  // with this option, according to the CSS-Loader README
  // (https://github.com/webpack/css-loader#sourcemaps)
  // In our experience, they generally work as expected,
  // just be aware of this issue when enabling this option.
  // 是否开启 cssSourceMap
  cssSourceMap: false
 }
}

在使用npm run build进行webpack打包后,发布的项目可能会遇到图片等找不到的情况。

这里有一个万能解决办法:

    1. 将config/index.js 里面的 assetsPublicPath:'/' 改为assetsPublicPath:'./'  

    2. build/util.js里面的

if (options.extract) {
       return ExtractTextPlugin.extract({
              use: loaders,
              fallback: 'vue-style-loader',
              publicPath:'/'
  })

    将其中的publicPath改为:publicPath:'../../'就可以了。这样打包出来的路径就是正确的了。

    第一个是为了改变js中引入图片的路径,改为./ 就是指在当前路径,这个.代表的路径就是assetsRoot+assetsSubDictionary,我这里定位到dist/static/ ,加上图片前缀img,就可以找到了。

    第二种是为了改变vue文件中使用style样式里面例如background:url('xxx'),这样的路径,因为style最终变成css文件在dist/static/css里面,我们的图片放在dist/static/img中,那么加上../../变成dist目录下,默认的目录前缀是static,img是图片默认前缀,这样就可以定位到图片。

vue-cli构建的项目中请求代理与项目打包

vue-cli构建的项目中,生产模式下的打包路径、与生产模式下的请求代理简单示意

总结

以上所述是小编给大家介绍的vue-cli webpack模板项目搭建及打包时路径问题的解决方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
鼠标图片振动代码
Jul 06 Javascript
jquery如何改变html标签的样式(两种实现方法)
Jan 16 Javascript
jQuery操作JSON的CRUD用法实例
Feb 25 Javascript
js仿百度登录页实现拖动窗口效果
Mar 11 Javascript
JS Array创建及concat()split()slice()的使用方法
Jun 03 Javascript
仿百度换肤功能的简单实例代码
Jul 11 Javascript
url传递的参数值中包含&时,url自动截断问题的解决方法
Aug 02 Javascript
js canvas实现放大镜查看图片功能
Jun 08 Javascript
React Native实现地址挑选器功能
Oct 24 Javascript
npm scripts 使用指南详解
Oct 08 Javascript
vue中实现点击按钮滚动到页面对应位置的方法(使用c3平滑属性实现)
Dec 29 Javascript
JavaScript的Set数据结构详解
Feb 18 Javascript
vue bus全局事件中心简单Demo详解
Feb 26 #Javascript
详解Angular系列之变化检测(Change Detection)
Feb 26 #Javascript
Bootstrap4如何定制自己的颜色和风格
Feb 26 #Javascript
vue-cli下的vuex的简单Demo图解(实现加1减1操作)
Feb 26 #Javascript
使用vue-cli编写vue插件的方法
Feb 26 #Javascript
使用ngrok+express解决本地环境中微信接口调试问题
Feb 26 #Javascript
element-ui 表格实现单元格可编辑的示例
Feb 26 #Javascript
You might like
php从右向左/从左向右截取字符串的实现方法
2011/11/28 PHP
初步介绍PHP扩展开发经验分享
2012/09/06 PHP
Yii框架中memcache用法实例
2014/12/03 PHP
php通过baihui网API实现读取word文档并展示
2015/06/22 PHP
Laravel如何使用Redis共享Session
2018/02/23 PHP
用JavaScrpt实现文件夹简单轻松加密的实现方法图文
2008/09/08 Javascript
一组JS创建和操作表格的函数集合
2009/05/07 Javascript
经典海量jQuery插件 大家可以收藏一下
2010/02/07 Javascript
Prototype源码浅析 String部分(三)之HTML字符串处理
2012/01/15 Javascript
jquery获取form表单input元素值的简单实例
2016/05/30 Javascript
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
2016/09/05 Javascript
jquery html5 视频播放控制代码
2016/11/06 Javascript
Node.js编写CLI的实例详解
2017/05/17 Javascript
node.js中grunt和gulp的区别详解
2017/07/17 Javascript
node内置调试方法总结
2018/02/22 Javascript
Vue使用.sync 实现父子组件的双向绑定数据问题
2019/04/04 Javascript
基于elementUI使用v-model实现经纬度输入的vue组件
2019/05/12 Javascript
Element InfiniteScroll无限滚动的具体使用方法
2020/07/27 Javascript
鸿蒙系统中的 JS 开发框架
2020/09/18 Javascript
Python性能提升之延迟初始化
2016/12/04 Python
Sublime开发python程序的示例代码
2018/01/24 Python
Python小游戏之300行代码实现俄罗斯方块
2019/01/04 Python
python实现可变变量名方法详解
2019/07/01 Python
Python拼接字符串的7种方式详解
2020/03/19 Python
Python定时任务APScheduler原理及实例解析
2020/05/30 Python
Python selenium模块实现定位过程解析
2020/07/09 Python
详解移动端html5页面长按实现高亮全选文本内容的兼容解决方案
2016/12/03 HTML / CSS
德国汉莎航空中国官网: Lufthansa中国
2017/03/30 全球购物
什么是ESB?请介绍一下ESB?
2015/05/27 面试题
普通简短的个人自我评价
2014/02/15 职场文书
三八妇女节趣味活动方案
2014/08/23 职场文书
出售房屋协议书范本
2014/10/06 职场文书
张丽莉观后感
2015/06/16 职场文书
源码分析Redis中 set 和 sorted set 的使用方法
2022/03/22 Redis
JS中forEach()、map()、every()、some()和filter()的用法
2022/05/11 Javascript
使用CSS实现百叶窗效果示例代码
2023/05/07 HTML / CSS