从零开始搭建VUE项目

前言

      此样板面向大型,严肃的项目,并假定您对 Webpack 和 vue-loader 有些熟悉。 请务必阅读 vue-loader 的常见工作流配方的文档。

如果您只想尝试 vue-loader 或者鞭打一个快速原型,请改用 webpack-simple 模板。

快速开始:

    要使用这个模板,可以用 vue-cli 来支持一个项目。 建议使用 npm 3+ 更高效的依赖关系树:

$ npm install -g vue-cli
$ vue init webpack my-project
$ cd my-project
$ npm install
$ npm run dev

项目结构:

.
├── build/                      # webpack 配置文件
│   └── ...
├── config/
│   ├── index.js                # 主要项目配置
│   └── ...
├── src/
│   ├── main.js                 # 应用入口文件
│   ├── App.vue                 # 主应用程序组件
│   ├── components/             # ui 组件
│   │   └── ...
│   └── assets/                 # 模块资源(由 webpack 处理)
│       └── ...
├── static/                     # 纯静态资源(直接复制)
├── test/
│   └── unit/                   # 单元测试
│   │   ├── specs/              # 测试 spec 文件
│   │   ├── index.js            # 测试构建条目文件
│   │   └── karma.conf.js       # 测试跑步者配置文件
│   └── e2e/                    # e2e 测试
│   │   ├── specs/              # 测试 spec 文件
│   │   ├── custom-assertions/  # e2e 测试的自定义断言
│   │   ├── runner.js           # 测试跑步脚本
│   │   └── nightwatch.conf.js  # 测试跑步者配置文件
├── .babelrc                    # babel 配置
├── .postcssrc.js               # postcss 配置
├── .eslintrc.js                # eslint 配置
├── .editorconfig               # editor 配置
├── index.html                  # index.html 模板
└── package.json                # 构建脚本和依赖关系

下面详细讲解下这个项目解构:

   build/

        此目录包含开发服务器和生产 webpack 构建的实际配置。 通常,您不需要触摸这些文件,除非您要自定义 Webpack 加载器,在这种情况下,您应该看看 build / webpack.base.conf.js。

   config/index.js

        这是显示构建设置的一些最常见配置选项的主配置文件。 有关详细信息,请参阅开发期间的 API 代理和后端框架集成。

    src/

        这是你的大部分应用程序代码所在的位置。如何构建此目录中的所有内容,主要取决于您; 如果您使用 Vuex,您可以查阅 Vuex 应用程序的建议。

    static/

        此目录是您不想使用 Webpack 进行处理的静态资源的一个逃生舱口。 它们将直接复制到生成 webpack 建立资产的同一个目录中。

有关详细信息,请参阅处理静态资产。

    test/unit

        包含单元测试相关文件。 有关详细信息,请参阅单元测试

    test/e2e

         包含 e2e 测试相关文件。 有关详细信息,请参阅端到端测试。

 index.html

         这是我们的单页应用程序的模板 index.html。 在开发和构建期间,Webpack 将生成资产,并将生成的资产的 URL 自动注入到此模板中以呈现最终的 HTML。

    package.json

        包含所有构建依赖项和构建命令的 NPM 软件包元文件。

  构建命令:

    

npm run dev

    启动 Node.js 本地开发服务器。 有关详细信息,请参阅开发期间的 API 代理。

        . 用于单个文件 Vue 组件的 Webpack + vue-loader。
        . 状态保存热重载
        . 状态保存编译错误覆盖
        . 使用 ESLint 保存
        . 源地图

npm run build

    建立资源进行生产。 有关详细信息,请参阅与后端框架集成。

        . 用 UglifyJS 缩小了 JavaScript。

        .HTML 用 html-minifier 缩小。
        . 将所有组件的 CSS 提取到单个文件中,并用 cssnano 进行缩小。
        . 使用版本散列编辑的所有静态资源都可以进行高效的长期缓存,并且生成 index.html 是自动生成的,具有适当的 URL 到这些生成的资产。

npm run unit

    使用 Karma 在 PhantomJS 中进行单元测试。 有关详细信息,请参阅单元测试

         . 在测试文件中支持 ES2015 +。

        . 支持所有 webpack 加载器。
        . 轻松模拟注射。

npm run e2e

    使用 Nightwatch 进行端到端测试。 有关详细信息,请参阅端到端测试 

        . 在多个浏览器中并行运行测试。

        . 开箱即用的一个命令:
        . 硒和 chromedriver 依赖关系自动处理。
        . 自动生成 Selenium 服务器。

  Linter 配置:

    此样板使用 ESLint 作为 linter,并使用标准预设与一些小的定制。如果您对默认的 linting 规则不满意,您可以选择几种:

        1. 覆盖.eslintrc.js 中的各个规则。 例如,您可以添加以下规则来强制执行分号,而不是省略它们:

// .eslintrc.js
"semi": [2, "always"]

        2. 在生成项目时选择不同的 ESLint 预设,例如 eslint-config-airbnb。

        3. 在生成项目并定义自己的规则时,为 ESLint 预设选择“无”。 有关详细信息,请参阅 ESLint 文档。

  预处理器:

    此样板为大多数流行的 CSS 预处理器(包括 LESS,SASS,Stylus 和 PostCSS)预先配置了 CSS 提取。 要使用预处理器,您需要做的就是为其安装适当的 webpack 加载器。 例如,要使用 SASS:

npm install sass-loader node-sass --save-dev

    请注意,您还需要安装 node-sass,因为 sass-loader 将其视为对等依赖关系。

  在组件内部使用预处理器:

    安装完成后,您可以使用 * .vue 组件中的预处理器,使用 <style> 标签上的 lang 属性:   

<style lang="scss">
/* write SASS! */
</style>

  关于 SASS 语法的注释:

    lang =“scss”对应于 CSS-superset 语法(带大括号和分号)。

    lang =“sass”对应于基于缩进的语法。

  PostCSS:

    默认情况下,* .vue 文件中的样式通过 PostCSS 管道传输,因此您不需要使用特定的加载器。 您可以在 vue 块下简单添加要在 build / webpack.base.conf.js 中使用的 PostCSS 插件:

// build/webpack.base.conf.js
module.exports = {
  // ...
  vue: {
    postcss: [/* your plugins */]
  }
}

    有关详细信息,请参阅vue-loader's的相关文档。

  Standalone CSS Files:

    为了确保一致的提取和处理,建议从您的根 App.vue 组件导入全局独立样式文件,例如:

<!-- App.vue -->
<style src="./styles/global.less" lang="less"></style>

    请注意,您应该仅为自己为您的应用程序编写的样式。 对于现有的图书馆 引导或语义 UI,您可以将它们放在 / 静态中,并直接在 index.html 中引用它们。 这避免了额外的构建时间,也更适合浏览器缓存。 (见 Static Asset Handling

 处理静态资产 (Static Assets):

    您将在项目结构中注意到,静态资产有两个目录:src / assets 和 static /。 他们有什么区别?

Webpacked 资产:

    为了回答这个问题,我们首先需要了解 Webpack 如何处理静态资产。 在 * .vue 组件中,所有的模板和 CSS 都由 vue-html-loader 和 css-loader 解析来查找资源 URL。 例如,在 <img src =“./ logo.png”> 和 background:url(./ logo.png)中,“./logo.png”是相对的资产路径,将由 Webpack 解析为模块依赖关系。

因为 logo.png 不是 JavaScript,当被视为模块依赖关系时,我们需要使用 url-loader 和 file-loader 来处理它。 此样板已经为您配置了这些加载程序,因此您可以免费获得文件名指纹和条件 base64 内联等功能,同时可以使用相对 / 模块路径,而不必担心部署。

由于这些资源可能在构建过程中被内联 / 复制 / 重命名,所以它们基本上是您的源代码的一部分。 这就是为什么建议将 Webpack 处理的静态资产放在 / src 中,沿着其他源文件。 实际上,您甚至不必将它们全部放在 / src / assets 中:您可以根据使用它们的模块 / 组件进行组织。 例如,您可以将每个组件放在自己的目录中,其静态资产就在它的旁边。

资产解决规则:

    . 相对网址,例如 ./assets/logo.png 将被解释为模块依赖关系。 它们将被基于 Webpack 输出配置的自动生成的 URL 替换。

    . 非前缀网址,例如 assets / logo.png 将被视为与相对 URL 相同,并被翻译成./assets/logo.png。

    . 前缀为〜的 URL 被视为模块请求,类似于 require('some-module / image.png')。 如果要使用 Webpack 的模块解析配置,则需要使用此前缀。 例如,如果您有资产的解决别名,则需要使用 <img src =“〜assets / logo.png”> 来确保别名符合要求。

    . 根相对 URL,例如 /assets/logo.png 根本没有被处理。

  在 JavaScript 中获取资源路径:    

    为了使 Webpack 返回正确的资源路径,您需要使用 require('./ relative / path / to / file.jpg'),这将由文件加载程序处理,并返回已解析的 URL。 例如:

computed: {background () {
    return require('./bgs/' + this.id + '.jpg')}}

    注意上面的例子将包括最终构建中的./bgs/ 下的每个图像。 这是因为 Webpack 无法猜测它们在运行时将被使用,所以它包括它们。

  “真实”静态资产:  

      相比之下,静态的文件根本不被 Webpack 处理:它们直接以相同的文件名复制到最终目的地。 您必须使用绝对路径引用这些文件,这是通过在 config.js 中加入 build.assetsPublicPath 和 build.assetsSubDirectory 来确定的。

    例如,使用以下默认值:

// config/index.js
module.exports = {
  // ...
  build: {
    assetsPublicPath: '/',
    assetsSubDirectory: 'static'
  }
}

    使用绝对 URL / static / [filename] 引用静态 / 中的任何文件。 如果将 assetSubDirectory 更改为资产,则这些 URL 将需要更改为 / assets / [filename]。

    我们将在后端集成部分中详细了解配置文件。

  环境变量:

     有时根据应用程序运行的环境具有不同的配置值是很实用的。

  举个例子:

// config/prod.env.js
module.exports = {
  NODE_ENV: '"production"',
  DEBUG_MODE: false,
  API_KEY: '"..."' // this is shared between all environments
}

// config/dev.env.js
module.exports = merge(prodEnv, {
NODE_ENV:
'"development"',
DEBUG_MODE:
true // this overrides the DEBUG_MODE value of prod.env
})

// config/test.env.js
module.exports = merge(devEnv, {
NODE_ENV:
'"testing"'
})

 

    注意:字符串变量需要被包装成单引号和双引号 '“...”'

    所以环境变量是:

      

  • Production
    • NODE_ENV = 'production',
    • DEBUG_MODE = false,
    • API_KEY = '...'
  • Development
    • NODE_ENV = 'development',
    • DEBUG_MODE = true,
    • API_KEY = '...'
  • Testing
    • NODE_ENV = 'testing',
    • DEBUG_MODE = true,
    • API_KEY = '...'

     我们可以看到,test.env 继承了 dev.env,dev.env 继承了 prod.env。

  用法:

    在代码中使用环境变量很简单。 例如:

Vue.config.productionTip = process.env.NODE_ENV === 'production'

  与后端框架集成:

    如果您正在构建纯静态应用程序(与后端 API 分开部署的应用程序),则可能甚至不需要编辑 config / index.js。 但是,如果要将此模板与现有的后端框架集成,例如 Rails / Django / Laravel 拥有自己的项目结构,您可以编辑 config / index.js,将前端资源直接生成到后台项目中。

    我们来看看默认的 config / index.js:

// config/index.js
var path = require('path')

module.exports = {
build: {
index: path.resolve(__dirname,
'dist/index.html'),
assetsRoot: path.resolve(__dirname,
'dist'),
assetsSubDirectory:
'static',
assetsPublicPath:
'/',
productionSourceMap:
true
},
dev: {
port:
8080,
proxyTable: {}
}
}

    在构建部分中,我们有以下选项:

        build.index

    必须是本地文件系统上的绝对路径。

如果您使用带有后端框架的此模板,则可以相应地编辑 index.html,并将此路径指向由您的后端应用程序呈现的视图文件,例如。 Rails 应用的 app / views / layouts / application.html.erb 或 Laravel 应用程序的 resources / views / index.blade.php。

        build.assetsRoot

    必须是本地文件系统上的绝对路径。

这应该指向包含应用程序的所有静态资源的根目录。 例如,公开 / 为 Rails / Laravel。

      build.assetsSubDirectory

    在 build.assetsRoot 中的此目录下嵌入 webpack 生成的资源,以便它们与 build.assetsRoot 中可能具有的其他文件不混合。 例如,如果 build.assetsRoot 是 / path / to / dist,并且 build.assetsSubDirectory 是静态的,则所有 Webpack 资源都将以 path / to / dist / static 生成。

  此目录将在每次构建之前进行清理,因此只应包含生成生成的资源。

静态中的文件将在构建期间按原样复制到该目录中。 这意味着如果您更改此前缀,则所有绝对 URL 引用 static / 中的文件也将需要更改。 有关详细信息,请参阅 Handling Static Assets

     build.assetsPublicPath

    这应该是您的 build.assetsRoot 将通过 HTTP 提供的 URL 路径。 在大多数情况下,这将是根(/)。 只有当您的后端框架提供具有路径前缀的静态资产时,才能更改此选项。 在内部,这是作为 output.publicPath 传递给 Webpack。

     build.productionSourceMap

    是否生成源地图进行生产构建。

    dev.port

    指定要监听的服务器的端口。

    dev.proxyTable

    定义开发人员服务器的代理规则。 有关详细信息,请参阅 API Proxying During Development

  开发期间的 API 代理:

    当将此样板与现有后端集成时,通常需要在使用 dev 服务器时访问后端 API。 为了实现这一点,我们可以并行(或远程)运行 dev 服务器和 API 后端,并让 dev 服务器将所有 API 请求代理到实际的后端。

    要配置代理规则,请在 config / index.js 中编辑 dev.proxyTable 选项。 dev 服务器正在使用 http 代理中间件进行代理,因此您应参考其文档以获取详细的用法。 但这是一个简单的例子:

// config/index.js
module.exports = {
  // ...
  dev: {
    proxyTable: {
      // proxy all requests starting with /api to jsonplaceholder
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
}

    以上示例将代理请求 / api / posts / 1 到 http://jsonplaceholder.typicode.com/posts/1.

  网址匹配:

    除了静态网址之外,您还可以使用 glob 模式来匹配网址,例如 / API/ **。 有关详细信息,请参阅上下文匹配。 此外,您可以提供一个过滤器选项,该选项可以是自定义函数,用于确定请求是否应被代理:

proxyTable: {
  '**': {
    target: 'http://jsonplaceholder.typicode.com',
    filter: function (pathname, req) {
      return pathname.match('^/api') && req.method === 'GET'
    }
  }
}

    单元测试:

    本样板用于单元测试的工具概述:

       .Karma:启动浏览器的测试运行器,运行测试并将结果报告给我们。

      .karma-webpack:使用 Webpack 捆绑我们的测试的 Karma 插件。

      . 摩卡:我们编写测试规范的测试框架。
      .Chai:提供更好的断言语法的测试断言库。
      .Sinon:提供间谍,存根和模拟的测试实用程序库。

    Chai 和 Sinon 是使用 karma-sinon-chai 进行集成的,所以所有 Chai 接口(应该是,期望,断言)和 sinon 都可以在测试文件中全球使用。

  和文件:

      index.js

    这是由 karma-webpack 用于捆绑所有测试代码和源代码(为了覆盖目的))的条目文件。 你可以忽略它大部分。

      specs/

    该目录是您编写实际测试的地方。 您可以在测试中使用完整的 ES2015 + 和所有受支持的 Webpack 加载器。

      karma.conf.js

    这是 Karma 配置文件。 有关详细信息,请参阅Karma docs 。

      在更多浏览器中运行测试

    您可以在多个真正的浏览器中运行测试,方法是在 test / unit / karma.conf.js 中安装更多的业务发射器并调整浏览器字段。

      模拟依赖

    默认情况下,此样板安装了注入装载机。 有关 * .vue 组件的使用,请参阅 vue-loader 文档进行测试。

  端到端测试:

    此样板使用 Nightwatch.js 进行 e2e 测试。 Nightwatch.js 是一个高度集成的 e2e 测试赛跑者,构建在硒上。 这个样板附带了 Selenium 服务器和 Chromedriver 二进制文件,为您预配置,所以你不必搞砸自己。

    我们来看看 test / e2e 目录中的文件:

        runner.js

    启动开发服务器的 Node.js 脚本,然后启动 Nightwatch 以对其执行测试。 这是运行 npm 运行 e2e 时运行的脚本。

        nightwatch.conf.js

    夜视配置文件。 有关详细信息,请参阅 Nightwatch 的配置文档。

        custom-assertions/

    可以在夜视测试中使用的自定义断言。 有关详细信息,请参阅 Nightwatch 的文档编写自定义声明。

        specs/

    你的实际测试! 有关详细信息,请参阅 Nightwatch 的文档测试和 API 参考。

      在更多浏览器中运行测试

    要配置哪些浏览器运行测试,请在 test / e2e / nightwatch.conf.js 中的“test_settings”下添加一个条目,以及 test / e2e / runner.js 中的 --env 标志。 如果您希望在诸如 SauceLabs 之类的服务上配置远程测试,您可以根据环境变量使 Nightwatch 配置有条件,或者完全使用单独的配置文件。 有关更多详细信息,请参阅 Nightwatch 在 Selenium 上的文档。

  预售 SEO

    如果您希望预先投放一旦推送到生产时不会显着更改的路线,请使用此 Webpack 插件:prerender-spa-plugin,它已经过 Vue 测试。 对于频繁更改的页面,Prerender.io 和 Netlify 都提供定期重新预览您的搜索引擎内容的计划。

        使用 prerender-spa-plugin 

    将其安装为开发人员依赖关系:

npm install --save-dev prerender-spa-plugin

    需要在 build / webpack.prod.conf.js 中:

// 该行应该位于其他“进口”生活的文件的顶部
var PrerenderSpaPlugin = require('prerender-spa-plugin')

    在 plugins 数组中(也在 build / webpack.prod.conf.js 中)进行配置:

new PrerenderSpaPlugin(
  // Path to compiled app
  path.join(__dirname, '../dist'),
  // List of endpoints you wish to prerender
  [ '/' ]
)

    如果您还想预先投射 / 关于和 / 接触,那么该数组将是 ['/','/ about','/ contact']。

    启用 vue-router 的历史记录模式:

const router = new VueRouter({
mode: 'history',
routes: [...]
})

 

这篇文章就分享到这里了。欢迎关注下面的公众号,进一步技术交流: