必经之路·基于vue的项目搭建

前言

日常的开发中,我们大部分时间可能迭代需求或是修改bug,如果不是公司初始员工或是公司不重视项目重构,很难接触到从0到1搭建项目。而后的接入的开发,往往类似定时向架构中修修补补,也会发现很多不合理地方,体量大的项目更难有精力与排期时间去更改。所以呢,本篇咱们一起去了解,初始搭建、配置并且扩展性强的项目的一些小细节,其实初始工作很重要,会在以后开发、迭代、扩展场景上会很能体现出好处。欢迎提建议或是错误指正

项目基于vue搭建

项目构建说明

基础架构搭建

  • 本项目代码事例,使用 vue-cli 的3.8.4版本创建,初始化安装vuex,vue-router,node-sass,scss[可选自己喜好的预处理器],babel,eslint模块。后续业务新增需求,可自定义安装相关依赖模块。
  • 最新脚手架创建项目采用了零配置理念,故新增配置文件(vue.config.js,.env.test,.env.production,.env.development),一般常用三种环境,若多个环境可自定义。
  • vue.config.js 文件配置详情,可点击查看配置代码
  • vue.config.js 官方配置文档 GO

包管理器的选择及配置相关文件

当然这不是必须,个人喜好选择,也可继续使用npm

预处理器

根据个人喜好,使用预处理器。常用预处理器三种,sass、less、stylus。

个人偏向使用sass,初始化安装sass会自动安装sass-loadernode-sass。或已初始化,手动使用命令安装 yarn add sass-loader node-sass -D。就可以使用sass的 使用变量优美的嵌套规则混合器等等。具体可参考 官方文档了解。

框架UI

根据项目场景,自定义UI框架。个人喜好,移动端使用有赞的vant,PC端使用饿了么的element框架,毕竟框架维护有保障。

本实例使用有赞的移动端框架vant,安装vant、babel-plugin-import模块,babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式,以减少代码体积和冗余模块。

1.安装运行命令 yarn add vantyarn add babel-plugin-impor -D
2.在babel.config.js中,配置按需引入代码

eslint规范代码

初始化安装项目后,会生成一个 .eslintrc.js文件,若个人喜好代码风格,可在该文件内的rules属性配置。

注意: 鉴于多人开发,可能某一模块风格各异,可新增.eslintignore.js,忽略语法检查文件,以免多人项目习惯不同导致不同的基本代码规范不同。

移动端适配问题

  1. 采用阿里的 lib-flexible 移动端解决方案,来设置rem基准值
  2. postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem
  3. 这样的好处,节省了设计稿的像素值转化适配值了,更加专注开发

需在vue.config.js内postcss内,配置相关参数,详见代码

减少打包体积

  1. index.html配置各模式兼容问题,及vue.config.js打包生产环境使用兼容cdn,详见代码
  2. 使用 compression-webpack-plugin 模块,解决打包体积过大等问题,项目vue.config.js部分代码如下:
// 1. 构建时开启gzip,降低服务器压缩对CPU资源的占用,服务器也要相应开启gzip
      productionGzip &&
        myConfig.plugins.push(
          new CompressionWebpackPlugin({
            // asset: '[path].gz[query]',
            algorithm: "gzip",
            test: new RegExp(
              "\\.(" + productionGzipExtensions.join("|") + ")$"
            ),
            threshold: 8192,
            minRatio: 0.8
          })
        );
  1. 可将生产环境npm包(包模块)转CDN,然后在index.html通过htmlWebpackPlugin模块转化,可想而知打包部署的时间和编译后的体积变得更加轻便。

注意,下面externals 对象的key对应npm包,val对应包暴露出来的全局函数名

vue.config.js 里面三部分代码:

// 2. 生产环境npm包转CDN(以下包模块不打包)
      myConfig.externals = {
        'vue': "Vue",
        "vue-router": "VueRouter",
        'vuex': "Vuex"
      };

// .......

/**
    * 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改
    */
config.plugin("html").tap(args => {
    if (process.env.NODE_ENV === "development") {
        args[0].cdn = cdn.dev;
    } else {
        args[0].cdn = cdn.build;
    }
    return args;
});

// .......

let cdn = {
  // 开发环境
  dev: {
    css: [],
    js: []
  },
  // 生产环境
  build: {
    css: [],
    js: [
      "https://cdn.jsdelivr.net/combine/npm/vue@2.6.10/dist/vue.min.js," +
        "npm/vue-router@3.0.3/dist/vue-router.min.js," +
        "npm/vuex@3.0.1/dist/vuex.min.js"
    ]
  }
};

index.html 里面部分代码:

<body>
    <noscript>
        <strong>We're sorry but simple doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- 使用CDN加速的JS文件,配置在vue.config.js下  preload -->
    <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
        <link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="preload" as="script">
    <% } %>
    <!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
    <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
        <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
    <% } %>
    <!-- built files will be auto injected -->
</body>

需安装 compression-webpack-plugin 模块

网络请求

  1. 采用axios 模块,来进行发起服务器端请求
  2. 网络请求封装,约定基础请求与业务线接口分开,格式详见代码
  3. 封装的基础请求,设置了axios的响应拦截器及域名统一管理,项目部分代码如下:
// request interceptor
service.interceptors.request.use(
  config => {
    // Do something before request is send
    return config;
  },
  error => {
    Promise.reject(error);
  }
);
// response interceptor
service.interceptors.response.use(
  response => {
    const res = response.data;
    if (res.code !== 200) {
      Toast(res.message);
      return Promise.reject(res);
    } else {
      return response.data;
    }
  },
  error => {
    //  1.判断请求超时
    if (
      error.code === "ECONNABORTED" &&
      error.message.indexOf("timeout") !== -1
    ) {
      console.log("服务器访问超时,请稍后重试!");
    }
    return Promise.reject(error);
  }
);

需安装 axios 模块,封装代码查看

静态图片采用svg

  1. svg为矢量图,缩放不失真,常用于项目中图标等
  2. 减少静态资源体积
  3. 具体配置,可分为三步:
    • 组件编写,并注册全局组件
    • svg入口文件,引入svg组件及设置svg图标存放文件夹
    • 项目入口文件,引入svg入口文件
    • vue.conf.js 相关配置

vue.conf.js 配置代码如下

// svg loader
const svgRule = config.module.rule("svg"); // 找到svg-loader
svgRule.uses.clear(); // 清除已有的loader, 如果不这样做会添加在此loader之后
svgRule.exclude.add(/node_modules/); // 正则匹配排除node_modules目录
svgRule // 添加svg新的loader处理
    .test(/\.svg$/)
    .use("svg-sprite-loader")
    .loader("svg-sprite-loader")
    .options({
    symbolId: "[name]"
    });

// 修改images loader 添加svg处理
const imagesRule = config.module.rule("images");
imagesRule.exclude.add(resolve("src/icons"));
config.module.rule("images").test(/\.(png|jpe?g|gif|svg)(\?.*)?$/);

需安装 svg-sprite-loader 模块,使用详情可看项目代码 或 可参考这位老兄

移动端测试打印

鉴于H5运行移动设备,发布后无法像浏览器那样有控制台分析遇到的问题。
vconsole模块插件解决了这类问题,在项目入口文件使用以下代码,控制台只展示除正式环境外。

// 移动端打印,生产环境不显示
if (!process.env.NODE_ENV !== "production") {
  Vue.prototype.$vConsole = new VConsole();
}

需安装 yarn add vconsole -D 模块,具体代码可看项目仓库代码

全局样式配置

  1. 开启一个项目,我们首先想到要确保代码书写样式在各个终端显示一致;

  2. 对设觉比较敏感的前端工作人员,会发现UI设计这块,他们有项目统一的色调(主题色、字号色、边框、阴影等),我们前端也可统一配置样式变量,保证代码整洁性和可维护;

  3. 之后开发开发着,突然发现很多类似同样样式操作(譬如设置下边框,设置文字溢出效果,动画等),也可统一设置全局,便于各个组件使用;

  4. 呼呼呼~,平常大家使用的vant或ElementUI的功能性组件,突然产品、或者UI不满足这个框架的组件的UI,需要重写,我们也可以在设置的样式文件统一设置。

全局样式入口文件 index.scss,部分代码如下:

/**
* 全局引入样式
*/

@import "./normalize.css"; // css标准格式设置
@import "./themeColor.scss"; // 项目配色方案
@import "./resetFrame.scss"; // 重置引入第三方框架样式,例如vant或ElementUi


/* 通用相关样式操作 */
...
  • css标准格式设置,采用大家比较常用的 normalize.css
  • 项目主题色样式及更改框架组件UI样式均在全局入口样式引入
  • 全局入口样式 可以在 main.js 或者分流的 bridge.js引入都可。也可在 vue.config.js加载预处理模块引入,代码如下:
//向 CSS 相关的 loader 传递选项(支持 css-loader postcss-loader sass-loader less-loader stylus-loader)
loaderOptions: {
    // css: {},
    postcss: {
        plugins: [
            autoprefixer(),
            pxtorem({
            rootValue: 37.5,
            propList: ["*", "!font-size"]
            })
        ]
    },
    sass: {
        data: `@import "@/styles/index.scss";`
    }
}

项目实例相关代码查看 GO

辅助函数

可自行配置文件,毕竟应用场景不同。下面,配置统用性比较高的几个文件,在utils文件夹下

  1. index.js 辅助函数库,项目中复用、独立性强与业务代码无关函数,存放于此。以前总结函数库,可查看
  2. const.js 常量文件,存放一些注册全局常量
  3. global.js VUE全局函数,挂在VUE实例原型prototype上,以便vue实例通过this访问高频方法
  4. bridge.js main.js 的入口js文件的分流文件,避免main.js过于臃肿。

项目实例代码可查看 GO

状态管理模式

状态管理也或叫是数据共享池或叫仓库。事实证明,项目中越来越常用数据管理。你可能利用公交车bus事件(on,emit), 或是props传值,也或是H5的storage存储等等,当然可以达到组件间的传值,但很会杂乱的值的变化,无法有效的跟踪,而vuex很好的做到这点。 vue的传值方式,可预览我写的 花里胡哨的vue传值

故搭建新项目,都会使用vuex来管理数据,只是使用程度、模式不一致而已,vuex文档

托管项目中全局数据

将 token(用户凭证)、device(设备环境)地理位置、城市等等,全局使用的、且独立的数据存放于仓库,便于取,有记录的存,有条理性记录公共的数据变化。这种方式也就是store(仓库)托管全局、共享的数据.

vuex项目结构,详见仓库代码

项目运行指令

  • 安装依赖
yarn 或 yarn install
  • 运行项目
yarn serve
  • 打包测试
yarn build:test
  • 打包正式
yarn build
  • 运行测试单元
yarn test
  • 格式化代码(规范代码)
yarn lint

项目仓库代码

生活寄语

158-500x500.jpg

爱代码,爱生活

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350