面試官:自己搭建過vue開發(fā)環(huán)境嗎?

開篇

原文地址:https://www.ccode.live/lentoo/list/33

項目代碼:https://github.com/lentoo/vue-webpack-template

前段時間殊橙,看到群里一些小伙伴面試的時候被面試官問到這類題目辐宾。平時大家開發(fā)vue項目的時候狱从,相信大部分人都是使用 vue-cli腳手架生成的項目架構,然后
npm run install 安裝依賴叠纹,npm run serve啟動項目然后就開始寫業(yè)務代碼了季研。

但是對項目里的webpack封裝和配置了解的不清楚,容易導致出問題不知如何解決誉察,或者不會通過webpack去擴展新功能与涡。

該篇文章主要是想告訴小伙伴們,如何一步一步的通過 webpack4來搭建自己的vue開發(fā)環(huán)境

首先我們要知道 vue-cli生成的項目冒窍,幫我們配置好了哪些功能递沪?

  1. ES6代碼轉(zhuǎn)換成ES5代碼
  2. scss/sass/less/stylus轉(zhuǎn)css
  3. .vue文件轉(zhuǎn)換成js文件
  4. 使用 jpgpng综液,font等資源文件
  5. 自動添加css各瀏覽器產(chǎn)商的前綴
  6. 代碼熱更新
  7. 資源預加載
  8. 每次構建代碼清除之前生成的代碼
  9. 定義環(huán)境變量
  10. 區(qū)分開發(fā)環(huán)境打包跟生產(chǎn)環(huán)境打包
  11. ....
image

1. 搭建 webpack 基本環(huán)境

該篇文章并不會細講 webpack 是什么東西款慨,如果還不是很清楚的話,可以先去看看 webpack官網(wǎng)

簡單的說谬莹,webpack是一個模塊打包機檩奠,可以分析你的項目依賴的模塊以及一些瀏覽器不能直接運行的語言jsxvue等轉(zhuǎn)換成 js附帽、css文件等埠戳,供瀏覽器使用。

image

1.1 初始化項目

在命令行中執(zhí)行 npm init 然后一路回車就行了蕉扮,主要是生成一些項目基本信息整胃。最后會生成一個 package.json 文件

npm init

1.2 安裝webpack

image

1.3 寫點小代碼測試一下webpack是否安裝成功了

新建一個src文件夾,然后再建一個main.js文件

// src/main.js
console.log('hello webpack')

然后在 package.json 下面加一個腳本命令

image

然后運行該命令

npm run serve

如果在 dist 目錄下生成了一個main.js文件喳钟,則表示webpack工作正常

2. 開始配置功能

  • 新建一個 build 文件夾屁使,用來存放 webpack配置相關的文件
  • build文件夾下新建一個webpack.config.js,配置webpack的基本配置
  • 修改 webpack.config.js配置
image
  • 修改package.json 文件奔则,將之前添加的 serve 修改為
"serve": "webpack ./src/main.js --config ./build/webpack.config.js"

2.1 配置 ES6/7/8 轉(zhuǎn) ES5代碼

  • 安裝相關依賴
npm install babel-loader @babel/core @babel/preset-env
  • 修改webpack.config.js配置
image
  • 在項目根目錄添加一個 babel.config.js 文件
image
  • 然后執(zhí)行 npm run serve 命令蛮寂,可以看到 ES6代碼被轉(zhuǎn)成了ES5代碼了

2.1.1 ES6/7/8 Api 轉(zhuǎn)es5

babel-loader只會將 ES6/7/8語法轉(zhuǎn)換為ES5語法,但是對新api并不會轉(zhuǎn)換易茬。

我們可以通過 babel-polyfill 對一些不支持新語法的客戶端提供新語法的實現(xiàn)

  • 安裝
npm install @babel/polyfill
  • 修改webpack.config.js配置

entry 中添加 @babel-polyfill

image

2.1.2 按需引入polyfill

2.1.2 和 2.1.1 只需要配置一個就行

修改時間 2019-05-05酬蹋、 來自評論區(qū) 兮漫天 的提醒

  • 安裝相關依賴
npm install core-js@2 @babel/runtime-corejs2 -S
  • 修改 babel-config.js
image

配置了按需引入 polyfill 后,用到es6以上的函數(shù)抽莱,babel會自動導入相關的polyfill范抓,這樣能大大減少 打包編譯后的體積

2.2 配置 scss 轉(zhuǎn) css

在沒配置 css 相關的 loader 時,引入scss食铐、css相關文件打包的話匕垫,會報錯

  • 安裝相關依賴
npm install sass-loader dart-sass css-loader style-loader -D

sass-loader, dart-sass主要是將 scss/sass 語法轉(zhuǎn)為css

css-loader主要是解析 css 文件

style-loader 主要是將 css 解析到 html頁面 的 style

  • 修改webpack.config.js配置
image

2.3 配置 postcss 實現(xiàn)自動添加css3前綴

  • 安裝相關依賴
npm install postcss-loader autoprefixer -D
  • 修改webpack.config.js配置
image
  • 在項目根目錄下新建一個 postcss.config.js
image

2.3 使用 html-webpack-plugin來創(chuàng)建html頁面

使用 html-webpack-plugin來創(chuàng)建html頁面,并自動引入打包生成的js文件

  • 安裝依賴
npm install html-webpack-plugin -D
  • 新建一個 public/index.html 頁面
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
</body>
</html>
  • 修改 webpack-config.js 配置
    image

2.4 配置 devServer 熱更新功能

通過代碼的熱更新功能璃岳,我們可以實現(xiàn)不刷新頁面的情況下年缎,更新我們的頁面

  • 安裝依賴
npm install webpack-dev-server -D
  • 修改webpack.config.js配置

通過配置 devServerHotModuleReplacementPlugin 插件來實現(xiàn)熱更新

image

2.5 配置 webpack 打包 圖片、媒體铃慷、字體等文件

  • 安裝依賴
npm install file-loader url-loader -D

file-loader 解析文件url单芜,并將文件復制到輸出的目錄中

url-loader 功能與 file-loader 類似,如果文件小于限制的大小犁柜。則會返回 base64 編碼洲鸠,否則使用 file-loader 將文件復制到輸出的目錄中

  • 修改 webpack-config.js 配置
    添加 rules 配置,分別對 圖片馋缅,媒體扒腕,字體文件進行配置
// build/webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {
  // 省略其它配置 ...
  module: {
    rules: [
      // ...
      {
        test: /\.(jpe?g|png|gif)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                    name: 'img/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'media/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'fonts/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
    ]
  },
  plugins: [
    // ...
  ]
}

3. 讓 webpack 識別 .vue 文件

  • 安裝需要的依賴文件
npm install vue-loader vue-template-compiler cache-loader thread-loader -D
npm install vue -S

vue-loader 用于解析.vue文件

vue-template-compiler 用于編譯模板

cache-loader 用于緩存loader編譯的結果

thread-loader 使用 worker 池來運行loader,每個 worker 都是一個 node.js 進程萤悴。

  • 修改 webpack.config.js配置
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  // 指定打包模式
  mode: 'development',
  entry: {
    // ...
  },
  output: {
    // ...
  },
  devServer: {
    // ...
  },
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.runtime.esm.js'
    },
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'thread-loader'
          },
          {
            loader: 'vue-loader',
            options: {
              compilerOptions: {
                preserveWhitespace: false
              },
            }
          }
        ]
      },
      {
        test: /\.jsx?$/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'thread-loader'
          },
          {
            loader: 'babel-loader'
          }
        ]
      },
      // ...
    ]
  },
  plugins: [
    // ...
    new VueLoaderPlugin()
  ]
}
  • 測試一下
  1. 在 src 新建一個 App.vue
// src/App.vue
<template>
  <div class="App">
    Hello World
  </div>
</template>

<script>
export default {
  name: 'App',

  data() {
    return {};
  }
};
</script>

<style lang="scss" scoped>
.App {
  color: skyblue;
}
</style>
  1. 修改 main.js
import Vue from 'vue'
import App from './App.vue'

new Vue({
  render: h => h(App)
}).$mount('#app')
  1. 運行一下

npm run serve

4. 定義環(huán)境變量

通過 webpack提供的DefinePlugin插件瘾腰,可以很方便的定義環(huán)境變量

plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        VUE_APP_BASE_URL: JSON.stringify('http://localhost:3000')
      }
    }),
]

5. 區(qū)分生產(chǎn)環(huán)境和開發(fā)環(huán)境

新建兩個文件

  • webpack.dev.js 開發(fā)環(huán)境使用

  • webpack.prod.js 生產(chǎn)環(huán)境使用

  • webpack.config.js 公用配置

  • 開發(fā)環(huán)境與生產(chǎn)環(huán)境的不同

5.1 開發(fā)環(huán)境

  1. 不需要壓縮代碼
  2. 需要熱更新
  3. css不需要提取到css文件
  4. sourceMap
  5. ...

5.2 生產(chǎn)環(huán)境

  1. 壓縮代碼
  2. 不需要熱更新
  3. 提取css,壓縮css文件
  4. sourceMap
  5. 構建前清除上一次構建的內(nèi)容
  6. ...
  • 安裝所需依賴
npm i @intervolga/optimize-cssnano-plugin mini-css-extract-plugin clean-webpack-plugin webpack-merge copy-webpack-plugin -D
  1. @intervolga/optimize-cssnano-plugin 用于壓縮css代碼
  2. mini-css-extract-plugin 用于提取css到文件中
  3. clean-webpack-plugin 用于刪除上次構建的文件
  4. webpack-merge 合并 webpack配置
  5. copy-webpack-plugin 用戶拷貝靜態(tài)資源

5.3 開發(fā)環(huán)境配置

  • build/webpack.dev.js
// build/webpack.dev.js
const merge = require('webpack-merge')
const webpackConfig = require('./webpack.config')
const webpack = require('webpack')
module.exports = merge(webpackConfig, {
  mode: 'development',
  devtool: 'cheap-module-eval-source-map',
  module: {
    rules: [
      {
        test: /\.(scss|sass)$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2
            }
          },
          {
            loader: 'sass-loader',
            options: {
              implementation: require('dart-sass')
            }
          },
          {
            loader: 'postcss-loader'
          }
        ]
      },
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('development')
      }
    }),
  ]
})
  • webpack.config.js
// build/webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  entry: {
    // 配置入口文件
    main: path.resolve(__dirname, '../src/main.js')
  },
  output: {
    // 配置打包文件輸出的目錄
    path: path.resolve(__dirname, '../dist'),
    // 生成的 js 文件名稱
    filename: 'js/[name].[hash:8].js',
    // 生成的 chunk 名稱
    chunkFilename: 'js/[name].[hash:8].js',
    // 資源引用的路徑
    publicPath: '/'
  },
  devServer: {
    hot: true,
    port: 3000,
    contentBase: './dist'
  },
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.runtime.esm.js'
    },
    extensions: [
      '.js',
      '.vue'
    ]
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'cache-loader'
          },
          {
            loader: 'vue-loader',
            options: {
              compilerOptions: {
                preserveWhitespace: false
              },
            }
          }
        ]
      },
      {
        test: /\.jsx?$/,
        loader: 'babel-loader'
      },

      {
        test: /\.(jpe?g|png|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'img/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'media/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 4096,
              fallback: {
                loader: 'file-loader',
                options: {
                  name: 'fonts/[name].[hash:8].[ext]'
                }
              }
            }
          }
        ]
      },
    ]
  },
  plugins: [
    new VueLoaderPlugin(),

    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '../public/index.html')
    }),
    new webpack.NamedModulesPlugin(),
    new webpack.HotModuleReplacementPlugin(),
  ]
}

5.4 生產(chǎn)環(huán)境配置

const path = require('path')
const merge = require('webpack-merge')
const webpack = require('webpack')
const webpackConfig = require('./webpack.config')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssnanoPlugin = require('@intervolga/optimize-cssnano-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = merge(webpackConfig, {
  mode: 'production',
  devtool: '#source-map',
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          name: 'chunk-vendors',
          test: /[\\\/]node_modules[\\\/]/,
          priority: -10,
          chunks: 'initial'
        },
        common: {
          name: 'chunk-common',
          minChunks: 2,
          priority: -20,
          chunks: 'initial',
          reuseExistingChunk: true
        }
      }
    }
  },
  module: {
    rules: [
      {
        test: /\.(scss|sass)$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              importLoaders: 2
            }
          },
          {
            loader: 'sass-loader',
            options: {
              implementation: require('dart-sass')
            }
          },
          {
            loader: 'postcss-loader'
          }
        ]
      },
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: 'production'
      }
    }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:8].css',
      chunkFilename: 'css/[name].[contenthash:8].css'
    }),
    new OptimizeCssnanoPlugin({
      sourceMap: true,
      cssnanoOptions: {
        preset: [
          'default',
          {
            mergeLonghand: false,
            cssDeclarationSorter: false
          }
        ]
      }
    }),
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../public'),
        to: path.resolve(__dirname, '../dist')
      }
    ]),
    new CleanWebpackPlugin()
  ]
})

5.5 修改package.json

"scripts": {
    "serve": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
},

6 打包分析

有的時候覆履,我們需要看一下webpack打包完成后蹋盆,到底打包了什么東西,

這時候就需要用到這個模塊分析工具了 webpack-bundle-analyzer

  • 安裝依賴
npm install --save-dev webpack-bundle-analyzer
  • 修改webpack-prod.js配置硝全,在 plugins屬性中新增一個插件

在開發(fā)環(huán)境中栖雾,我們是沒必要進行模塊打包分析的,所以我們將插件配置在了生產(chǎn)環(huán)境的配置項中

image
  • 運行打包命令
npm run build

執(zhí)行成功后會自動打開這個頁面

image

7. 集成 VueRouter,Vuex

  1. 首先是安裝相關依賴
npm install vue-router vuex --save

7.1 集成 Vue-Router

  • 新增視圖組件
    src 目錄下新增兩個視圖組件 src/views/Home.vuesrc/views/About.vue
// src/views/Home.vue
<template>
  <div class="Home">
    <h2>Home</h2>
  </div>
</template>

<script>
export default {
  name: 'Home',

  data() {
    return {};
  }
};
</script>

<style lang="scss" scoped>
</style>

About.vue 內(nèi)容跟 Home.vue 差不多伟众,將里面的 Home 換成 About 就OK了

  • 新增路由配置文件

src 目錄下新增一個 router/index.js 文件

// src/router/index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Home from '../views/Home';
import About from '../views/About';
Vue.use(VueRouter)
export default new VueRouter({
  mode: 'hash',
  routes: [
    {
      path: '/Home',
      component: Home
    },
    {
      path: '/About',
      component: About
    },
    {
      path: '*',
      redirect: '/Home'
    }
  ]
})
  • 修改 main.js 文件
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
  • 修改 App.vue 組件
// App.vue
// 在 template 中添加
// src/App.vue
<template>
  <div class="App">
    Hello World
  </div>
  <div>
      // router-link 組件 用來導航到哪個路由
      <router-link to="/Home">go Home</router-link>
      <router-link to="/About">go About</router-link>
    </div>
    <div>
      // 用于展示匹配到的路由視圖組件
      <router-view></router-view>
    </div>
</template>

<script>
export default {
  name: 'App',

  data() {
    return {};
  }
};
</script>

<style lang="scss" scoped>
.App {
  color: skyblue;
}
</style>

運行 npm run serve 命令析藕,如沒配置錯誤,是可以看到點擊不同的路由凳厢,會切換到不同的路由視圖

7.2 配置路由懶加載

在沒配置路由懶加載的情況下账胧,我們的路由組件在打包的時候,都會打包到同一個js文件去数初,當我們的視圖組件越來越多的時候找爱,就會導致這個 js 文件越來越大。然后就會導致請求這個文件的時間變長泡孩,最終影響用戶體驗

  1. 安裝依賴
npm install @babel/plugin-syntax-dynamic-import --save-dev
  1. 修改babel.config.js
module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        useBuiltIns: "usage"
      }
    ]
  ],
  plugins: [
     // 添加這個
    '@babel/plugin-syntax-dynamic-import'
  ]
}
  1. 修改 router/index.js 路由配置文件
import Vue from 'vue'
import VueRouter from "vue-router";
Vue.use(VueRouter)
export default new VueRouter({
  mode: 'hash',
  routes: [
    {
      path: '/Home',
      component: () => import(/* webpackChunkName: "Home" */ '../views/Home.vue')
      // component: Home
    },
    {
      path: '/About',
      component: () => import(/* webpackChunkName: "About" */ '../views/About.vue')
      // component: About
    },
    {
      path: '*',
      redirect: '/Home'
    }
  ]
})
  1. 運行命令 npm run build
    查看是否生成了 Home...js 文件 和 About...js 文件

7.3 集成 Vuex

  1. src 目錄下新建一個 store/index.js 文件
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
  counter: 0
}
const actions = {
  add: ({commit}) => {
    return commit('add')
  }
}
const mutations = {
  add: (state) => {
    state.counter++
  }
}
const getters = {
  getCounter (state) {
    return state.counter
  }
}
export default new Vuex.Store({
  state,
  actions,
  mutations,
  getters
})
  1. 修改 main.js 文件 導入 vuex
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'  // ++
new Vue({
  router,
  store,    // ++
  render: h => h(App)
}).$mount('#app')
  1. 修改 App.vue 车摄,查看 vuex 配置效果
// App.vue
<template>
  <div class="App">
    <div>
      <router-link to="/Home">go Home</router-link>
      <router-link to="/About">go About</router-link>
    </div>
    <div>
      <p>{{getCounter}}</p>
      <button @click="add">add</button>
    </div>
    <div>
      <router-view></router-view>
    </div>
  </div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
  name: 'App',
  data() {
    return {};
  },
  computed: {
    ...mapGetters(['getCounter'])
  },
  methods: {
    ...mapActions(['add'])
  }
};
</script>
<style lang="scss" scoped>
.App {
  text-align: center;
  color: skyblue;
  font-size: 28px;
}
</style>
  1. 運行命令 npm run serve

當點擊按鈕的時候,可以看到我們的getCounter一直在增加

8 總結

到目前為止仑鸥,我們已經(jīng)成功的自己搭建了一個 vue 開發(fā)環(huán)境吮播,不過還是有一些功能欠缺的,有興趣的小伙伴可以交流交流眼俊。在搭建過程中意狠,還是會踩很多坑的。

如果還不熟悉 webpack 的話疮胖,建議自己搭建一次环戈∶瓢澹可以讓自己能深入的理解 vue-cli 替我們做了什么

項目代碼:https://github.com/lentoo/vue-webpack-template

image

推薦閱讀

  1. 使用 webpack 的各種插件提升你的開發(fā)效率

  2. vue-cli3 項目從搭建優(yōu)化到docker部署

  3. Event Loop 原來是這么回事

  4. 通過vue-cli3構建一個SSR應用程序

歡迎關注

歡迎關注公眾號“碼上開發(fā)”,每天分享最新技術資訊

image
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末院塞,一起剝皮案震驚了整個濱河市遮晚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拦止,老刑警劉巖县遣,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異汹族,居然都是意外死亡萧求,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門顶瞒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夸政,“玉大人,你說我怎么就攤上這事搁拙∶胧幔” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵箕速,是天一觀的道長酪碘。 經(jīng)常有香客問我,道長盐茎,這世上最難降的妖魔是什么兴垦? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮字柠,結果婚禮上探越,老公的妹妹穿的比我還像新娘。我一直安慰自己窑业,他們只是感情好钦幔,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著常柄,像睡著了一般鲤氢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上西潘,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天卷玉,我揣著相機與錄音,去河邊找鬼喷市。 笑死相种,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的品姓。 我是一名探鬼主播寝并,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼箫措,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了衬潦?” 一聲冷哼從身側響起蒂破,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎别渔,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惧互,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡哎媚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了喊儡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拨与。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖艾猜,靈堂內(nèi)的尸體忽然破棺而出买喧,到底是詐尸還是另有隱情,我是刑警寧澤匆赃,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布淤毛,位于F島的核電站,受9級特大地震影響算柳,放射性物質(zhì)發(fā)生泄漏低淡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一瞬项、第九天 我趴在偏房一處隱蔽的房頂上張望蔗蹋。 院中可真熱鬧,春花似錦囱淋、人聲如沸猪杭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽皂吮。三九已至,卻和暖如春称鳞,著一層夾襖步出監(jiān)牢的瞬間涮较,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工冈止, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留狂票,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓熙暴,卻偏偏與公主長得像闺属,于是被迫代替她去往敵國和親慌盯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容