github地址(内含简单例子)
使用技术栈
webpack(^2.6.1)
webpack-dev-server(^2.4.5)
vue(^2.3.3)
vuex(^2.3.1)
vue-router(^2.5.3)
vue-loader(^12.2.1)
eslint(^3.19.0)
需要学习的知识
vue.js
vuex
vue-router
vue-loader
webpack2
eslint
内容相当多,尤其是webpack2教程,官方脚手架vue-cli虽然相当完整齐全,但是修改起来还是挺花时间,于是自己参照网上的资料和之前做过的项目用到的构建工具地去写了一个简单vue项目脚手架。适用于多页面spa模式的业务场景(每个模块都是一个spa)。比较简单,主要就是一个webpack.config.js文件,没有说特意地去划分成分webpack.dev.config.js、webpack.prov.config.js等等。下面是整个webpack.config.js文件代码:
1 const { resolve } = require('path') 2 const webpack = require('webpack') 3 const HtmlWebpackPlugin = require('html-webpack-plugin') 4 const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 const glob = require('glob') 6 7 module.exports = (options = {}) => { 8 // 配置文件,根据 run script不同的config参数来调用不同config 9 const config = require('./config/' + (process.env.npm_config_config || options.config || 'dev')) 10 // 遍历入口文件,这里入口文件与模板文件名字保持一致,保证能同时合成HtmlWebpackPlugin数组和入口文件数组 11 const entries = glob.sync('./src/modules/*.js') 12 const entryJsList = {} 13 const entryHtmlList = [] 14 for (const path of entries) { 15 const chunkName = path.slice('./src/modules/'.length, -'.js'.length) 16 entryJsList[chunkName] = path 17 entryHtmlList.push(new HtmlWebpackPlugin({ 18 template: path.replace('.js', '.html'), 19 filename: 'modules/' + chunkName + '.html', 20 chunks: ['manifest', 'vendor', chunkName] 21 })) 22 } 23 // 处理开发环境和生产环境ExtractTextPlugin的使用情况 24 function cssLoaders(loader, opt) { 25 const loaders = loader.split('!') 26 const opts = opt || {} 27 if (options.dev) { 28 if (opts.extract) { 29 return loader 30 } else { 31 return loaders 32 } 33 } else { 34 const fallbackLoader = loaders.shift() 35 return ExtractTextPlugin.extract({ 36 use: loaders, 37 fallback: fallbackLoader 38 }) 39 } 40 } 41 42 const webpackObj = { 43 entry: Object.assign({ 44 vendor: ['vue', 'vuex', 'vue-router'] 45 }, entryJsList), 46 // 文件内容生成哈希值chunkhash,使用hash会更新所有文件 47 output: { 48 path: resolve(__dirname, 'dist'), 49 filename: options.dev ? 'static/js/[name].js' : 'static/js/[name].[chunkhash].js', 50 chunkFilename: 'static/js/[id].[chunkhash].js', 51 publicPath: config.publicPath 52 }, 53 54 externals: { 55 56 }, 57 58 module: { 59 rules: [ 60 // 只 lint 本地 *.vue 文件,需要安装eslint-plugin-html,并配置eslintConfig(package.json) 61 { 62 enforce: 'pre', 63 test: /.vue$/, 64 loader: 'eslint-loader', 65 exclude: /node_modules/ 66 }, 67 /* 68 69 70 [eslint资料] 71 */ 72 { 73 test: /\.js$/, 74 exclude: /node_modules/, 75 use: ['babel-loader', 'eslint-loader'] 76 }, 77 // 需要安装vue-template-compiler,不然编译报错 78 { 79 test: /\.vue$/, 80 loader: 'vue-loader', 81 options: { 82 loaders: { 83 sass: cssLoaders('vue-style-loader!css-loader!sass-loader', { extract: true }) 84 } 85 } 86 }, 87 { 88 // 需要有相应的css-loader,因为第三方库可能会有文件 89 // (如:element-ui) css在node_moudle 90 // 生产环境才需要code抽离,不然的话,会使热重载失效 91 test: /\.css$/, 92 use: cssLoaders('style-loader!css-loader') 93 }, 94 { 95 test: /\.(scss|sass)$/, 96 use: cssLoaders('style-loader!css-loader!sass-loader') 97 }, 98 { 99 test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,100 use: [101 {102 loader: 'url-loader',103 options: {104 limit: 10000,105 name: 'static/imgs/[name].[ext]?[hash]'106 }107 }108 ]109 }110 ]111 },112 113 plugins: [114 ...entryHtmlList,115 // 抽离css116 new ExtractTextPlugin({117 filename: 'static/css/[name].[chunkhash].css',118 allChunks: true119 }),120 // 抽离公共代码121 new webpack.optimize.CommonsChunkPlugin({122 names: ['vendor', 'manifest']123 }),124 // 定义全局常量125 // cli命令行使用process.env.NODE_ENV不如期望效果,使用不了,所以需要使用DefinePlugin插件定义,定义形式'"development"'或JSON.stringify('development')126 new webpack.DefinePlugin({127 'process.env': {128 NODE_ENV: options.dev ? JSON.stringify('development') : JSON.stringify('production')129 }130 })131 132 ],133 134 resolve: {135 // require时省略的扩展名,不再需要强制转入一个空字符串,如:require('module') 不需要module.js136 extensions: ['.js', '.json', '.vue', '.scss', '.css'],137 // require路径简化138 alias: {139 '~': resolve(__dirname, 'src'),140 // Vue 最早会打包生成三个文件,一个是 runtime only 的文件 vue.common.js,一个是 compiler only 的文件 compiler.js,一个是 runtime + compiler 的文件 vue.js。141 // vue.js = vue.common.js + compiler.js,默认package.json的main是指向vue.common.js,而template 属性的使用一定要用compiler.js,因此需要在alias改变vue指向142 vue: 'vue/dist/vue'143 },144 // 指定import从哪个目录开始查找145 modules: [146 resolve(__dirname, 'src'),147 'node_modules'148 ]149 },150 // 开启http服务,publicPath => 需要与Output保持一致 || proxy => 反向代理 || port => 端口号151 devServer: config.devServer ? {152 port: config.devServer.port,153 proxy: config.devServer.proxy,154 publicPath: config.publicPath,155 stats: { colors: true }156 } : undefined,157 // 屏蔽文件超过限制大小的warn158 performance: {159 hints: options.dev ? false : 'warning'160 },161 // 生成devtool,保证在浏览器可以看到源代码,生产环境设为false162 devtool: 'inline-source-map'163 }164 165 if (!options.dev) {166 webpackObj.devtool = false167 webpackObj.plugins = (webpackObj.plugins || []).concat([168 // 压缩js169 new webpack.optimize.UglifyJsPlugin({170 // webpack2,默认为true,可以不用设置171 compress: {172 warnings: false173 }174 }),175 // 压缩 loaders176 new webpack.LoaderOptionsPlugin({177 minimize: true178 })179 ])180 }181 182 return webpackObj183 }
上面的代码对于每个配置项都有注释说明,这里有几点需要注意的:
1. webpack.config.js导出的是一个function
之前项目的webpack.config.js是以对象形式export的,如下
1 module.exports = {2 entry: ...,3 output: {4 ...5 },6 ...7 }
而现在倒出来的是一个function,如下:
1 module.exports = (options = {}) => { 2 return {3 entry: ...,4 output: {5 ...6 },7 ...8 }9 }
这样的话,function会在执行webpack CLI的时候获取webpack的参数,通过options传进function,看一下package.json:
1 "local": "npm run dev --config=local",2 "dev": "webpack-dev-server -d --hot --inline --env.dev --env.config dev",3 "build": "rimraf dist && webpack -p --env.config prod" //rimraf清空dist目录
对于local
命令,我们执行的是dev
命令,但是在最后面会--config=local
,这是配置,这样我们可以通过process.env.npm_config_config
获取到,而对于dev
命令,对于--env XXX
,我们便可以在function获取option.config
= 'dev' 和 option.dev
= true的值,特别方便!以此便可以同步参数来加载不同的配置文件了。对于-d
、-p
不清楚的话,可以这里查看,很详细!
1 // 配置文件,根据 run script不同的config参数来调用不同config2 const config = require('./config/' + (process.env.npm_config_config || options.config || 'dev'))
2. modules放置模板文件、入口文件、对应模块的vue文件
将入口文件和模板文件放到modules目录(名字保持一致),webpack文件会通过glob读取modules目录,遍历生成入口文件对象和模板文件数组,如下:
1 const entries = glob.sync('./src/modules/*.js') 2 const entryJsList = {} 3 const entryHtmlList = [] 4 for (const path of entries) { 5 const chunkName = path.slice('./src/modules/'.length, -'.js'.length) 6 entryJsList[chunkName] = path 7 entryHtmlList.push(new HtmlWebpackPlugin({ 8 template: path.replace('.js', '.html'), 9 filename: 'modules/' + chunkName + '.html',10 chunks: ['manifest', 'vendor', chunkName]11 }))12 }
对于HtmlWebpackPlugin插件中几个配置项的意思是,template:模板路径,filename:文件名称,这里为了区分开来模板文件我是放置在dist/modules文件夹中,而对应的编译打包好的js、img(对于图片我们是使用file-loader、url-loader进行抽离,对于这两个不是很理解的,可以看这里)、css我也是会放在dist/下对应目录的,这样目录会比较清晰。chunks:指定插入文件中的chunk,后面我们会生成manifest文件、公共vendor、以及对应生成的jscss(名称一样)
3. 处理开发环境和生产环境ExtractTextPlugin的使用情况
开发环境,不需要把css进行抽离,要以style插入html文件中,可以很好实现热替换 生产环境,需要把css进行抽离合并,如下(根据options.dev区分开发和生产):
1 // 处理开发环境和生产环境ExtractTextPlugin的使用情况 2 function cssLoaders(loader, opt) { 3 const loaders = loader.split('!') 4 const opts = opt || {} 5 if (options.dev) { 6 if (opts.extract) { 7 return loader 8 } else { 9 return loaders10 }11 } else {12 const fallbackLoader = loaders.shift()13 return ExtractTextPlugin.extract({14 use: loaders,15 fallback: fallbackLoader16 })17 }18 }19 ...20 // 使用情况21 // 注意:需要安装vue-template-compiler,不然编译会报错22 {23 test: /\.vue$/,24 loader: 'vue-loader',25 options: {26 loaders: {27 sass: cssLoaders('vue-style-loader!css-loader!sass-loader', { extract: true })28 } }30 },31 ...32 {33 test: /\.(scss|sass)$/,34 use: cssLoaders('style-loader!css-loader!sass-loader')35 }
再使用ExtractTextPlugin合并抽离到static/css/
目录
4. 定义全局常量
cli命令行(webpack -p
)使用process.env.NODE_ENV不如期望效果,使用不了,所以需要使用DefinePlugin插件定义,定义形式'"development"'或JSON.stringify(process.env.NODE_ENV),我使用这样的写法'development',结果报错(针对webpack2),查找了一下网上资料,它是这样讲的,可以去看一下,设置如下:
1 new webpack.DefinePlugin({2 'process.env': {3 NODE_ENV: options.dev ? JSON.stringify('development') : JSON.stringify('production')4 }5 })
5. 使用eslint修正代码规范
通过eslint来检查代码的规范性,通过定义一套配置项,来规范代码,这样多人协作,写出来的代码也会比较优雅,不好的地方是,就是配置项太多,有些默认项设置我们不需要,但是确是处处限制我们,需要通过配置屏蔽掉,可以通过.eslintrc
文件或是package.json的eslintConfig
,还有其他方式,可以到中文网看,这里我用的是package.json方式,如下:
1 ... 2 "eslintConfig": { 3 "parser": "babel-eslint", 4 "extends": "enough", 5 "env": { 6 "browser": true, 7 "node": true, 8 "commonjs": true, 9 "es6": true10 }, 11 "rules": {12 "linebreak-style": 0,13 "indent": [2, 4],14 "no-unused-vars": 0,15 "no-console": 016 },17 "plugins": [18 "html"19 ]20 },21 ...
我们还需要安装 npm install eslint eslint-config-enough eslint-loader --save-dev
,eslint-config-enough是所谓的配置文件,这样package.json的内容才能起效,但是不当当是这样,对应编辑器也需要安装对应的插件,sublime text 3需要安装SublimeLinter、SublimeLinter-contrib-eslint插件。对于所有规则的详解,可以去看官网,也可以去这里看,很详细!
由于我们使用的是vue-loader,自然我们是希望能对.vue文件eslint,那么需要安装eslint-plugin-html,在package.json中进行配置。然后对应webpack配置:
1 {2 enforce: 'pre',3 test: /.vue$/,4 loader: 'eslint-loader',5 exclude: /node_modules/6 }
我们会发现webpack v1和v2之间会有一些不同,比如webpack1对于预先加载器处理的执行是这样的,
1 module: {2 preLoaders: [3 {4 test: /\.js$/,5 loader: "eslint-loader"6 }7 ]8 }
更多的不同可以到中文网看,很详细,不做拓展。
6. alias vue指向问题
1 ...2 alias: {3 vue: 'vue/dist/vue'4 }, 5 ...
Vue 最早会打包生成三个文件,一个是 runtime only 的文件 vue.common.js,一个是 compiler only 的文件 compiler.js,一个是 runtime + compiler 的文件 vue.js。vue.js = vue.common.js + compiler.js,默认package.json的main是指向vue.common.js,而template 属性的使用一定要用compiler.js,因此需要在alias改变vue指向
7. devServer的使用
之前的项目中使用的是用express启动http服务,webpack-dev-middleware+webpack-hot-middleware,这里会用到compiler+compilation,这个是webpack的编译器和编译过程的一些知识,也不是很懂,后续要去做做功课,应该可以加深对webpack运行机制的理解。这样做的话,感觉复杂很多,对于webpack2.0 devServer似乎功能更强大更加完善了,所以直接使用就可以了。如下:
1 devServer: { 2 port: 8080, //端口号 3 proxy: { //方向代理 /api/auth/ => http://api.example.dev 4 '/api/auth/': { 5 target: 'http://api.example.dev', 6 changeOrigin: true, 7 pathRewrite: { '^/api': '' } 8 } 9 },10 publicPath: config.publicPath,11 stats: { colors: true }12 }13 //changeOrigin会修改HTTP请求头中的Host为target的域名, 这里会被改为api.example.dev14 //pathRewrite用来改写URL, 这里我们把/api前缀去掉,直接使用/auth/请求
webpack 2 打包实战讲解得非常好,非常棒。可以去看一下,一定会有所收获!
8. 热重载原理
webpack中文网,讲的还算清楚,不过可能太笨,看起来还是云里雾里的,似懂非懂的,补补课,好好看看。
9. localtunnel的使用
Localtunnel 是一个可以让内网服务器暴露到公网上的开源项目,使用可以看这里,
1 $ npm install -g localtunnel2 $ lt --port 80803 your url is: https://uhhzexcifv.localtunnel.me
这样的话,可以把我们的本地网站暂时性地暴露到公网,可以对网站做一些线上线下对比,详细内容可以去了解一下localtunnel,这里讲的是通过上面配置,访问https://uhhzexcifv.localtunnel.me
,没有达到理想效果,出现了Invalid Host header
的错误,因为devServer缺少一个配置disableHostCheck: true
,这样的一个配置,很多文档上面都没有说明,字面上面的意思不要去检查Host
,这样设置,便可以绕过这一层检验,设置的配置项在optionsSchema.json中,issue可以看这里
文章内容可能会更新,可以关注github
以上是vue项目脚手架介绍的详细内容。更多信息请关注PHP中文网其他相关文章!

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

禅工作室 13.0.1
功能强大的PHP集成开发环境