create-webpack-app 是笔者对于日常工作中的基于 React/vue.js 技术栈与实践的沉淀,dev-config/* 与 package.json 构成了基础的脚手架,支持最新的开发流程与默认的生产环境优化;模板项目包含特性如下:
本部分即是针对 Vue.js 项目的脚手架,我们可以直接拷贝该项目来展示部分开发模式或者作为模板项目使用:
- #下载本项目git clone https: //github.com/wxyyxc1992/create-webpack-app
- #可以使用yarn install & npm start直接运行本项目#仅保留dev - config、package.json、src / client.js、src / ssr_server.js mkdir / path / to / your / project
- #拷贝必须的启动文件cp - r vue / dev - config / /path/to / your / project cp vue / package.json / path / to / your / project cp vue / src / client.js / path / to / your / project / src /
- #安装运行依赖cd / path / to / your / project
- yarn install / npm install
- #有时候需要安装better - npm - run npm install better - npm - run - g
- #启动项目npm start
- #编译为纯客户端部署模式,即单个html页面npm run build
- #进行依赖升级检查npm run update
本模板相较于官方的 webpack-simple 功能稍微复杂,并且引入了完整的 Flow、Jest 等技术栈配置,同时优化了 Webpack 的构建性能。
!Important! 项目尚未支持 SSR
create-webpack-app 默认的应用配置位于 dev-config/apps.config.js 文件中,该文件也是 dev-config/ 文件夹下唯一与应用业务相关的文件;该文件定义了不同应用中的需要配置的应用相关信息。create-webpack-app 定位为单项目多应用的模板,因此我们可以在 apps 键下配置项目设计的应用入口;在打包时会自动将多个应用并行编译并且提取出所有公共的代码。每个应用需要提供唯一编号、入口文件地址、模板页面、是否编译等信息;接下来 devServer 则是定义了当前正在开发的应用入口,ssrServer 定义了打包时需要使用的渲染服务器入口,其会在执行 npm run build:ssr 时调用,proxy 与 api 则定义了后端服务器信息,开发者可以根据业务需求自行使用。典型的 apps.config.js 文件配置如下:
- module.exports = {
- //基本的应用配置信息
- apps: [
- //HelloWorld
- {
- id: "pwa",
- src: "./pwa/client.js",
- indexPage: defaultIndexPage,
- compiled: true
- }],
- //开发入口配置
- devServer: {
- appEntrySrc: "./pwa/client.js",
- //当前待调试的APP的入口文件
- port: 3000 //监听的Server端口
- },
- //用于服务端渲染的Server路径
- ssrServer: {
- serverEntrySrc: "./pwa/ssr_server.js"
- },
- //依赖项配置
- proxy: {
- //后端服务器地址 http://your.backend/
- "/api/*": "http://localhost:3001"
- },
- //后端 api 配置,这样配置可以避免将测试服务器端口暴露出去
- api: {
- dev: {},
- prod: {}
- }
- };
应用入口文件则遵循官方的单文件组件范式:
- import Vue from 'vue';
- import App from './application/App.vue';
- new Vue({
- el: '#root',
- render: h = >h(App)
- });
在 dev-config/webpack/loaders.js 文件中定义了模板所需要的加载器,默认支持 js、jsx、vue、ts、tsx、css、scss、less、json 以及各种资源文件等常见格式。当我们执行 npm start 命令时,会自动启动 dev-config/server/devServer.js 文件中定义的 Webpack 开发服务器,该服务器会使用 dev-config/webpack.config.js 文件进行配置项生成。值得一提的是,WebpackDevServer 中的 contentBase 设置为了 path.join(__dirname,"../../public"),也就是将 /public 目录作为开发服务器的默认根目录。热加载配置包括以下步骤:
- entry = [`webpack - dev - server / client ? http: //0.0.0.0:${appsConfig.devServer.port}`,
- "webpack/hot/only-dev-server", require("./apps.config.js").devServer.appEntrySrc];
- ..."plugins": [...
create-webpack-app 支持 SCSS、CSS Modules 以及 styled-components 这三种样式定义方式。
create-webpack-app 使用了 CommonsChunkPlugin 进行代码分割,默认在 dev-config/webpack/plugins.js 文件中定义了对于 node_modules 中依赖文件的自动抽取:
- new webpack.optimize.CommonsChunkPlugin({
- name: "vendor",
- filename: "vendor.bundle.js",
- minChunks: ({
- resource
- }) = >resource && resource.indexOf("node_modules") >= 0 && resource.match(/\.(js|less|scss)$/)
- })
该插件会自动生成 vendor.bundle.js 文件,我们需要在应用入口文件之前引用它;开发者也可以自定义 CommonsChunkPlugin 插件以自定义需要提取的公共代码。
随着项目复杂度与体量的增加,我们发现初始化编译与增量编译的速度都有所下降,为了提升构建性能首先我们要做的就是保持 Webpack 版本的更新速度;此外,create-webpack-app 还默认启动了 DllPlugin 在开发状态下将所有的依赖提取为 dll 文件以提高增量编译的速度。因为考虑到灵活性,即随时有可能增减依赖的情况,create-webpack-app 目前设置的是每次使用 npm start 的时候都会重新生成 dll 文件;如果是已经稳定的项目可以考虑仅生成一次依赖。
- const path = require("path");
- const pkg = require("../package.json");
- const webpack = require("webpack");
- let dllConfig = {
- name: "vendor",
- entry: Object.keys(pkg.dependencies),
- output: {
- path: path.resolve(__dirname, "../public/dll"),
- filename: "vendor.bundle.js",
- library: "vendor_[hash]"
- },
- plugins: [new webpack.DllPlugin({
- name: "vendor_[hash]",
- path: path.resolve(__dirname, "../public/dll/manifest.json")
- })]
- };
- module.exports = dllConfig;
- // 在 public/index.html 文件中需要引入该依赖
- // index.html
- < script src = "dll/vendor.bundle.js" > </script>/
create-webpack-app 中也内置了其他的编译之后的代码性能优化插件,首先是利用 Webpack 3 的 Scope Hositing 特性来优化生成的模块;这一点需要使用 ModuleConcatenationPlugin 插件。此外,还使用了 PrepackWebpackPlugin 对于打包生成的文件进行过滤与重构;不过需要注意的是 PrepackWebpackPlugin 会较大地降低编译速度,因此也是可以根据实际的项目情况选用。
- // 使用 Scope Hositing 特性
- new webpack.optimize.ModuleConcatenationPlugin(),
- // 使用 Prepack 优化包体大小
- // 暂时存在 Bug,等待修复
- // 使用前 21 - 425
- // 使用后 21 - 433
- new PrepackWebpackPlugin({
- mathRandomSeed: "0"
- }),
create-webpack-app 中只是简单地使用了 Offline Plugin ,其配置如下:
- // webpack.config.js example
- var OfflinePlugin = require('offline-plugin');
- module.exports = {
- // ...
- plugins: [
- // ... other plugins
- // it's always better if OfflinePlugin is the last plugin added
- new OfflinePlugin()]
- // ...
- }
- // render.js
- require('offline-plugin/runtime').install();
观察网络面板中的资源请求情况,我们可以看到脚本等已经被缓存在了本地:
本小节仅代表本人个人意见,请多多指点
官方文档中介绍的单文件组件(Single File Component)包含了 template、script、style 这三个部分,笔者感觉算是典型的前端项目三要素。不过笔者习惯的开发模式是以 JavaScript 为中心,即 JavaScript 文件单独可测试,而不是和样式以及标签混合在一起(JSX 本质上也是 JavaScript)。因此在该模板中,笔者是将标签、样式与脚本分到了三个文件中:
- // App.js
- // @flow
- export
- default {
- name:
- "app",
- data() {
- return {
- msg: "Vue.js & Webpack App Boilerplate by 王下邀月熊"
- };
- }
- };
- // App.scss
- #app {
- font - family: 'Avenir',
- Helvetica,
- Arial,
- sans - serif; - webkit - font - smoothing: antialiased; - moz - osx - font - smoothing: grayscale;
- text - align: center;
- color: #2c3e50;
- margin - top: 60px;
- }
- h1,
- h2 {
- font - weight: normal;
- }
- ul {
- list - style - type: none;
- padding: 0;
- }
- li {
- display: inline - block;
- margin: 0 10px;
- }
- a {
- color: #42b983;
- }
- // App.vue
- < template > <div id = "app" > <img src = "../../public/assets/logo.png" > <h1 > {
- {
- msg
- }
- } < /h1>
- <h2>Essential Links</h2 > <ul > <li > <a href = "https://vuejs.org"target = "_blank" > Core Docs < /a></li > <li > <a href = "https://forum.vuejs.org"target = "_blank" > Forum < /a></li > <li > <a href = "https://gitter.im/vuejs/vue"target = "_blank" > Gitter Chat < /a></li > <li > <a href = "https://twitter.com/vuejs"target = "_blank" > Twitter < /a></li > </ul>
- <h2>Ecosystem</h2 > <ul > <li > <a href = "http://router.vuejs.org/"target = "_blank" > vue - router < /a></li > <li > <a href = "http://vuex.vuejs.org/"target = "_blank" > vuex < /a></li > <li > <a href = "http://vue-loader.vuejs.org/"target = "_blank" > vue - loader < /a></li > <li > <a href = "https://github.com/vuejs/awesome-vue"target = "_blank" > awesome - vue < /a></li > </ul>
- </div > </template>
- <script>
- import App from './App.js ';
- export default App;
- </script>
- <style lang="scss">
- @import "App";
- </style>'
笔者个人感觉这种模式更符合单一职责原则,对于复杂的组件能够提高代码可读性;同时将 JavaScript 代码独立出来也能更加方便地进行单元测试与类型检测等操作。
详细的 JavaScript 编程样式指南已经迁移到了 Web 项目开发风格指南 与 JavaScript 编程样式指南 ,涵盖了基本原则阐述、代码风格、代码格式化与语法检测、项目架构等几个部分。不过本部分建议是类似于 Create React APP 配置提交时自动进行格式化,首先需要安装如下依赖:
- npm install--save husky lint - staged prettier
- // or
- yarn add husky lint - staged prettier
然后在 package.json 中添加 Hook:
- "scripts": {
- "precommit": "lint-staged",
- ...
同时添加 lint-staged 配置:
- "dependencies": {
- // ...
- },
- +"lint-staged": { + "{src,stories}/**/*.{js,jsx,json,css}": [ + "prettier --single-quote --write", +"git add" + ] +
- },
- "scripts": {
这样当我们提交代码时就会自动使用 Prettier 优化代码,不过需要注意的是这种配置仅作用于根目录下;如果某个仓库中包含了多个应用配置,那么我们还需要在根目录下单独配置脚本。我们也可以使用 ./node_modules/.bin/prettier --single-quote --write "src/**/*.{js,jsx}" 来手动进行项目文件的格式化。另外因为模板项目时放置在了子文件下,如果使用者希望使用该特性需要手动地在 package.json 中添加 "precommit": "lint-staged" 这个配置。
来源: http://www.tuicool.com/articles/6RfEVna