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 相关文章推荐
artdialog的图片/标题以及关闭按钮不显示的解决方法
Jun 27 Javascript
使用GruntJS链接与压缩多个JavaScript文件过程详解
Aug 02 Javascript
js动态控制table的tr、td增加及删除的具体实现
Apr 30 Javascript
完美兼容各大浏览器获取HTTP_REFERER方法总结
Jun 24 Javascript
jquery操作select方法汇总
Feb 05 Javascript
JavaScript使用math.js进行精确计算操作示例
Jun 19 Javascript
微信小程序实现自定义picker选择器弹窗内容
May 26 Javascript
用js简单提供增删改查接口
May 12 Javascript
原生js实现的移动端可拖动进度条插件功能详解
Aug 15 Javascript
微信小程序 checkbox使用实例解析
Sep 09 Javascript
JavaScript undefined及null区别实例解析
Jul 21 Javascript
谈一谈vue请求数据放在created好还是mounted里好
Jul 27 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
DIY一个适配电脑声卡的动圈话筒放大器
2021/03/02 无线电
Godaddy空间Zend Optimizer升级方法
2010/05/10 PHP
PHP中输出转义JavaScript代码的实现代码
2011/04/22 PHP
PHP 获取文件权限函数介绍
2013/07/11 PHP
PHP5.3与5.5废弃与过期函数整理汇总
2014/07/10 PHP
php metaphone()函数的定义和用法
2016/05/15 PHP
贴一个在Mozilla中常用的Javascript代码
2007/01/09 Javascript
ASP Json Parser修正版
2009/12/06 Javascript
JavaScript中的Array对象使用说明
2011/01/17 Javascript
Js 获取Gridview选中行的内容操作步骤
2013/02/05 Javascript
js中的onchange和onpropertychange (onchange无效的解决方法)
2014/03/08 Javascript
让alert不出现弹窗的两种方法
2014/05/18 Javascript
提高NodeJS中SSL服务的性能
2014/07/15 NodeJs
基于Javascript实现返回顶部按钮
2016/02/29 Javascript
JSON字符串转换JSONObject和JSONArray的方法
2016/06/03 Javascript
详解vue表单——小白速看
2018/04/08 Javascript
AngularJS实现动态切换样式的方法分析
2018/06/26 Javascript
微信小程序之裁剪图片成圆形的实现代码
2018/10/11 Javascript
详解element-ui表格中勾选checkbox,高亮当前行
2019/09/02 Javascript
js实现简易计算器功能
2019/10/18 Javascript
Vue v-model组件封装(类似弹窗组件)
2020/01/08 Javascript
js实现随机点名器精简版
2020/06/29 Javascript
vue插件--仿微信小程序showModel实现模态提示窗功能
2020/08/19 Javascript
原生js+canvas实现验证码
2020/11/29 Javascript
[03:40]2014DOTA2国际邀请赛 B神专访:躲箭真的很难
2014/07/13 DOTA
Python实现线程状态监测简单示例
2018/03/28 Python
Python生成任意范围任意精度的随机数方法
2018/04/09 Python
django模板加载静态文件的方法步骤
2019/03/01 Python
Opencv-Python图像透视变换cv2.warpPerspective的示例
2019/04/11 Python
python使用pip安装SciPy、SymPy、matplotlib教程
2019/11/20 Python
学点简单的Django之第一个Django程序的实现
2021/02/24 Python
Tostadora意大利:定制T恤
2019/04/08 全球购物
收银员岗位职责
2014/02/07 职场文书
2015暑假社会调查报告
2015/07/13 职场文书
MySQL和Oracle批量插入SQL的通用写法示例
2021/11/17 MySQL
vue实现简易音乐播放器
2022/08/14 Vue.js