享慣了vue-cli2.0的自由那么擼一個(gè)react-cli吧

你是否對如何構(gòu)建一個(gè)react應(yīng)用得心應(yīng)手呢

create-react-app MyReactApp

npm run start

嚕嚕啦 多簡單主巍;

but 如果我要改一些配置呢?too young, too simple 能難倒我挪凑?

npm run eject  反編譯create-react-app的config到項(xiàng)目中

npm install react-app-rewired --save 了解下孕索?

好好好,但是您能不能自己寫一個(gè)呢躏碳?

搞旭。。。ののの

其實(shí)代碼我2018年3月份就寫好了肄渗,之后每天忙于寫業(yè)務(wù)代碼(-?-;)

package.json

{

  "name": "react-cli",

  "version": "0.0.1",

  "description": "React 16.0 boilerplate with react-router-dom, redux & webpack 4.x",

  "scripts": {

    "start": "webpack-dev-server --config build/webpack.dev.conf.js --progress --watch --colors --profile ",

    "build": "webpack -p --mode production --progress --config ./build/webpack.prod.conf.js"

  },

  "devDependencies": {

    "@babel/core": "^7.0.0",

    "@babel/plugin-syntax-dynamic-import": "^7.0.0",

    "@babel/plugin-syntax-object-rest-spread": "^7.0.0",

    "@babel/plugin-transform-runtime": "^7.0.0",

    "@babel/preset-env": "^7.0.0",

    "@babel/preset-react": "^7.0.0",

    "@babel/runtime": "^7.0.0",

    "@commitlint/cli": "^7.0.0",

    "@commitlint/config-conventional": "^7.0.1",

    "autoprefixer": "^9.0.0",

    "babel-core": "^6.26.3",

    "babel-eslint": "^8.2.6",

    "babel-loader": "^8.0.2",

    "babel-plugin-dynamic-import-node": "^2.2.0",

    "babel-plugin-import": "^1.8.0",

    "babel-plugin-module-resolver": "^3.1.1",

    "clean-webpack-plugin": "^0.1.19",

    "compression-webpack-plugin": "^1.1.11",

    "copy-webpack-plugin": "^4.5.2",

    "cross-env": "^5.2.0",

    "css-loader": "^1.0.0",

    "file-loader": "^2.0.0",

    "friendly-errors-webpack-plugin": "^1.7.0",

    "highcharts": "^6.1.2",

    "highcharts-react-official": "highcharts/highcharts-react",

    "html-webpack-plugin": "^3.2.0",

    "husky": "^0.14.3",

    "jest": "^23.4.1",

    "less": "^3.8.1",

    "less-loader": "^4.1.0",

    "lint-staged": "^7.2.2",

    "mini-css-extract-plugin": "^0.4.1",

    "node-notifier": "^5.2.1",

    "node-ssh": "^5.1.2",

    "portfinder": "^1.0.20",

    "postcss-import": "^11.1.0",

    "postcss-loader": "^2.1.6",

    "postcss-safe-parser": "^4.0.1",

    "prettier": "^1.14.2",

    "source-map-loader": "^0.2.3",

    "style-loader": "^0.21.0",

    "styled-components": "^3.4.5",

    "url-loader": "^1.0.1",

    "webpack": "^4.16.1",

    "webpack-bundle-analyzer": "^2.13.1",

    "webpack-cli": "^3.1.0",

    "webpack-dev-server": "^3.1.4",

    "webpack-merge": "^4.2.1"

  },

  "dependencies": {

    "@babel/plugin-proposal-class-properties": "^7.4.0",

    "@babel/plugin-proposal-decorators": "^7.4.0",

    "@babel/plugin-proposal-do-expressions": "^7.2.0",

    "@babel/plugin-proposal-export-default-from": "^7.2.0",

    "@babel/plugin-proposal-export-namespace-from": "^7.2.0",

    "@babel/plugin-proposal-function-bind": "^7.2.0",

    "@babel/plugin-proposal-function-sent": "^7.2.0",

    "@babel/plugin-proposal-logical-assignment-operators": "^7.2.0",

    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.2.0",

    "@babel/plugin-proposal-numeric-separator": "^7.2.0",

    "@babel/plugin-proposal-optional-chaining": "^7.2.0",

    "@babel/plugin-proposal-pipeline-operator": "^7.3.2",

    "@babel/plugin-proposal-throw-expressions": "^7.2.0",

    "@babel/plugin-syntax-import-meta": "^7.2.0",

    "antd": "^3.7.0",

    "axios": "^0.18.0",

    "babel-polyfill": "^6.26.0",

    "bignumber": "^1.1.0",

    "debug": "^4.1.1",

    "import-local": "^2.0.0",

    "js-base64": "^2.5.1",

    "js-cookie": "^2.2.0",

    "jsencrypt": "^3.0.0-rc.1",

    "memoize-one": "^5.0.1",

    "node-sass": "^4.11.0",

    "nzh": "^1.0.4",

    "pnp-webpack-plugin": "^1.4.1",

    "progress-bar-webpack-plugin": "^1.12.1",

    "react": "^16.4.1",

    "react-dom": "^16.4.1",

    "react-loadable": "^5.5.0",

    "react-redux": "^5.0.7",

    "react-router-config": "^5.1.1",

    "react-router-dom": "^4.3.1",

    "react-table": "^6.9.2",

    "react-transition-group": "^4.4.1",

    "redux": "^4.0.0",

    "redux-devtools-extension": "^2.13.8",

    "redux-logger": "^3.0.6",

    "redux-thunk": "^2.3.0",

    "sass-loader": "^7.1.0",

    "yargs": "^13.2.2"

  }

}

.babelrc

{

  "presets": [

    "@babel/preset-env",

    "@babel/preset-react"

  ],

  "plugins": [

    "@babel/plugin-syntax-dynamic-import",

    "@babel/plugin-transform-runtime",

    "dynamic-import-node",

    [

      "@babel/plugin-proposal-decorators",

      {

        "legacy": true

      }

    ],

    "@babel/plugin-proposal-class-properties",

    "@babel/plugin-syntax-import-meta",

    "@babel/plugin-proposal-json-strings",

    "@babel/plugin-proposal-function-sent",

    "@babel/plugin-proposal-export-namespace-from",

    "@babel/plugin-proposal-numeric-separator",

    "@babel/plugin-proposal-throw-expressions",

    "@babel/plugin-proposal-export-default-from",

    "@babel/plugin-proposal-logical-assignment-operators",

    "@babel/plugin-proposal-optional-chaining",

    [

      "@babel/plugin-proposal-pipeline-operator",

      {

        "proposal": "minimal"

      }

    ],

    "@babel/plugin-proposal-nullish-coalescing-operator",

    "@babel/plugin-proposal-do-expressions",

    "@babel/plugin-proposal-function-bind",

  ]

}

webpack.base.conf.js

'use strict'

const path = require('path');

const PnpWebpackPlugin = require('pnp-webpack-plugin');

function resolve (dir) {

  return path.join(__dirname, '..', dir)

}



module.exports = {

  context: path.resolve(__dirname, '../'),

  entry: {

    index: ['babel-polyfill','./src/index.js']

  },

  output: {

    path: path.resolve(__dirname, '../dist'),

    filename: 'app.[hash:8].js',

    publicPath: '/',

    libraryTarget: 'umd',

  },

  

  resolve: {

    // 自動(dòng)解析文件擴(kuò)展名(補(bǔ)全文件后綴)(從左->右)

    extensions: ['.js', '.jsx', '.json'],

    alias: {

      '@': resolve('src')

    },

    plugins: [

      // 正確解析程序所需的依賴的插件

      PnpWebpackPlugin,

    ],

  },

  resolveLoader: {

    plugins: [

      // 也與插件‘n’Play有關(guān)镇眷,但這一次它告訴Webpack從當(dāng)前的包中加載其加載程序

      PnpWebpackPlugin.moduleLoader(module),

    ],

  },

  module: {

    rules: [

      {

        test: /\.(js|jsx)$/,

        exclude: /node_modules/,

        enforce: 'pre',

        use: [{

          loader: 'babel-loader',

        }]

      },

      {

        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,

        loader: 'url-loader',

        options: {

          // 不寫fallback,file size 大于limit時(shí)翎嫡,會(huì)自動(dòng)調(diào)用file-loader欠动,但是使用的是默認(rèn)的[hash].[ext]無法指定路徑名和文件名

          // 顯示聲明 fallback之后,就可以將name傳至file-loader惑申。

          // 因?yàn)槭褂昧薈opyWebpackPlugin具伍,防止諸如[name][hash].[ext]和[name].[ext]文件同時(shí)存在

          // 特將文件名指定為[name].[ext]

          fallback: 'file-loader',

          name: 'assets/img/[name].[ext]',

          limit: 10000,

        }

      },

      {

        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,

        loader: 'url-loader',

        options: {

          fallback: 'file-loader',

          limit: 10000,

          name: 'assets/media/[name].[ext]',

        }

      },

      {

        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,

        loader: 'url-loader',

        options: {

          fallback: 'file-loader',

          limit: 10000,

          name: 'assets/fonts/[name].[ext]',

        }

      }  

    ]

  },

  node: {

    module: 'empty',

    dgram: 'empty',

    dns: 'mock',

    fs: 'empty',

    net: 'empty',

    tls: 'empty',

    child_process: 'empty',

  },

  performance: false,

}

webpack.dev.conf.js

const utils = require('./utils')

const webpack = require('webpack')

const merge = require('webpack-merge')

const path = require('path')

const baseWebpackConfig = require('./webpack.base.conf')

const CopyWebpackPlugin = require('copy-webpack-plugin')

const HtmlWebpackPlugin = require('html-webpack-plugin')

const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

const portfinder = require('portfinder')

const HOST = process.env.HOST

const PORT = (process.env.PORT && Number(process.env.PORT)) || '8080'



const devWebpackConfig = merge(baseWebpackConfig, {

  mode: 'development',

  optimization: {

    minimize: false,

    minimizer: [],

    splitChunks: {

      chunks: 'all',

      name:'vendor'

    },

  },

  module: {

    //合并styleloader

    rules: utils.styleLoaders({ sourceMap: true, usePostCSS: false, extract: false, })

  },

  // 源錯(cuò)誤檢查

  devtool: 'eval-source-map',

  devServer: {

    clientLogLevel: 'warning',

    //在開發(fā)單頁應(yīng)用時(shí)非常有用,它依賴于HTML5 history API圈驼,如果設(shè)置為true人芽,所有的跳轉(zhuǎn)將指向index.html

    historyApiFallback: true, 

    contentBase: path.resolve(__dirname, '../src'),

    compress: true,

    // 熱加載

    hot: true, 

    //自動(dòng)刷新

    inline: true, 

    //自動(dòng)打開瀏覽器

    open: false, 

    host: HOST||'localhost',

    port: PORT,

    // 在瀏覽器上全屏顯示編譯的errors或warnings。

    overlay: { warnings: false, errors: true }, 

    publicPath: '/',

    // 終端輸出的只有初始啟動(dòng)信息绩脆。webpack 的警告和錯(cuò)誤是不輸出到終端的

    proxy: {},

    quiet: true, 

    // 通過傳遞 true 開啟 polling啼肩,或者指定毫秒為單位進(jìn)行輪詢。默認(rèn)為false

    watchOptions: {

      poll: false

    }

  },

  plugins: [

    new webpack.DefinePlugin({

      ...process.env

    }),

    //開啟HMR(熱替換功能,替換更新部分,不重載頁面衙伶!)

    new webpack.HotModuleReplacementPlugin(),

    //顯示模塊相對路徑

    // new webpack.NamedModulesPlugin(),

    //不顯示錯(cuò)誤信息

    new webpack.NoEmitOnErrorsPlugin(),

    // https://github.com/ampedandwired/html-webpack-plugin

    //配置html入口信息

    new HtmlWebpackPlugin({

      filename: 'index.html',

      template: path.resolve(__dirname, '../index.html'),

      chunksSortMode: 'none',

      inject: true

    }),

    new CopyWebpackPlugin([{

      from: path.resolve(__dirname, '../static'),

      to: 'static',

      ignore: ['.*']

    }]),

  ]

})

module.exports = new Promise((resolve, reject) => {

    // 獲取當(dāng)前設(shè)定的端口

  portfinder.basePort = PORT

  portfinder.getPort((err, port) => {

    if (err) {

      reject(err)

    } else {

      // 發(fā)布新的端口祈坠,對于e2e測試

      process.env.PORT = port

      devWebpackConfig.devServer.port = port

      // 友好的報(bào)錯(cuò)插件

      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({

        compilationSuccessInfo: {

          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],

        },

        onErrors: utils.createNotifierCallback(),

      }))

      resolve(devWebpackConfig)

    }

  })
})

webpack.prod.conf.js

'use strict'

const path = require('path')

const utils = require('./utils')

const webpack = require('webpack')

const merge = require('webpack-merge')

const baseWebpackConfig = require('./webpack.base.conf')

const HtmlWebpackPlugin = require('html-webpack-plugin')

const CleanWebpackPlugin = require('clean-webpack-plugin');

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const BundleAnalyzerPlugin = process.env.NODE_ENV=== 'analysis' ? require('webpack-bundle-analyzer').BundleAnalyzerPlugin:null

const CopyWebpackPlugin = require('copy-webpack-plugin')



const env = process.env.NODE_ENV === 'testing'

  ? {NODE_ENV: '"testing"'}

  : {NODE_ENV: '"production"'}



const webpackConfig = merge(baseWebpackConfig, {

  mode: 'production',

  module: {

    //并入style-loader

    rules: utils.styleLoaders({

      sourceMap: false,

      extract: true,

      usePostCSS: true

    })

  },

  output: {

    path: path.resolve(__dirname, '../dist'),

    filename: ('js/[name].[hash:8].js'),

    chunkFilename: ('js/[name]-[id].[hash:8].js')

  },

  //4.0配置  重點(diǎn)

  optimization: {

    //它的作用是將包含chunks 映射關(guān)系的 list單獨(dú)從 app.js里提取出來,

    //因?yàn)槊恳粋€(gè) chunk 的 id 基本都是基于內(nèi)容 hash 出來的矢劲,

    //所以你每次改動(dòng)都會(huì)影響它赦拘,如果不將它提取出來的話,等于app.js每次都會(huì)改變芬沉。緩存就失效了躺同。

    runtimeChunk: {

      name: "manifest"

    },

    splitChunks: {

      chunks: 'all'

    }

    // splitChunks: {

    //   //默認(rèn)作用于異步chunk,值為all/initial/async/function(chunk),值為function時(shí)第一個(gè)參數(shù)為遍歷所有入口chunk時(shí)的chunk模塊丸逸,chunk._modules為gaichunk所有依賴的模塊蹋艺,通過chunk的名字和所有依賴模塊的resource可以自由配置,會(huì)抽取所有滿足條件chunk的公有模塊,以及模塊的所有依賴模塊黄刚,包括css

    //   chunks: "async”,

    //   //默認(rèn)值是30kb

    //   minSize: 30000,

    //   //被多少模塊共享  

    //   minChunks: 1,

    //   //所有異步請求不得超過5個(gè)  

    //   maxAsyncRequests: 5,

    //   //初始化并行請求不得超過3個(gè)  

    //   maxInitialRequests: 3,

    //   //打包后的名稱捎谨,默認(rèn)是chunk的名字通過分隔符(默認(rèn)是~)分隔開,如vendor~  

    //   name: true,

    //   //設(shè)置緩存組用來抽取滿足不同規(guī)則的chunk,下面以生成common為例  

    //   cacheGroups: { 

    //     common: {

    //       //抽取的chunk的名字

    //       name: 'common',

    //       //同外層的參數(shù)配置憔维,覆蓋外層的chunks涛救,以chunk為維度進(jìn)行抽取  

    //       chunks(chunk) { 

    //       },

    //       //可以為字符串,正則表達(dá)式业扒,函數(shù)检吆,以module為維度進(jìn)行抽取,只要是滿足條件的module都會(huì)被抽取到該common的chunk中程储,為函數(shù)時(shí)第一個(gè)參數(shù)是遍歷到的每一個(gè)模塊蹭沛,第二個(gè)參數(shù)是每一個(gè)引用到該模塊的chunks數(shù)組臂寝。自己嘗試過程中發(fā)現(xiàn)不能提取出css,待進(jìn)一步驗(yàn)證摊灭。

    //       test(module, chunks) {  

    //       },

    //     //優(yōu)先級咆贬,一個(gè)chunk很可能滿足多個(gè)緩存組,會(huì)被抽取到優(yōu)先級高的緩存組中

    //     priority: 10,  

    //     //最少被幾個(gè)chunk引用

    //     minChunks: 2,  

    //     //   如果該chunk中引用了已經(jīng)被抽取的chunk斟或,直接引用該chunk素征,不會(huì)重復(fù)打包代碼

    //     reuseExistingChunk: true,

    //     // 如果cacheGroup中沒有設(shè)置minSize萝挤,則據(jù)此判斷是否使用上層的minSize御毅,true:則使用0,false:使用上層minSize

    //     enforce: true  

    //     }

    //   }

    // }

  },

  plugins: [

    //清除目錄

    new CleanWebpackPlugin(path.resolve(__dirname, '../dist/*'), {

      root: path.resolve(__dirname, '../'),

      verbose: true,

      dry: false

    }),

    //允許創(chuàng)建一個(gè)在編譯時(shí)可以配置的全局常量怜珍。這可能會(huì)對開發(fā)模式和發(fā)布模式的構(gòu)建允許不同的行為非常有用

    new webpack.DefinePlugin({

      'process.env': env

    }),

    //壓縮css

    new MiniCssExtractPlugin({

      filename: 'css/[name].[hash:8].css',

      chunkFilename: 'css/[name]-[id].[hash:8].css',

    }),

    new HtmlWebpackPlugin({

      filename: 'index.html',

      template: path.resolve(__dirname, '../index.html'),

      title: 'React Demo',

      inject: true, // true->'head' || false->'body'

      minify: {

        //刪除Html注釋

        removeComments: true,

        //去除空格

        collapseWhitespace: true,

        //去除屬性引號

        removeAttributeQuotes: true

      },

      chunksSortMode: 'dependency'

    }),

    // 該插件會(huì)根據(jù)模塊的相對路徑生成一個(gè)四位數(shù)的hash作為模塊id, 建議用于生產(chǎn)環(huán)境端蛆。

    new webpack.HashedModuleIdsPlugin(),

    // 這個(gè)插件會(huì)在 webpack 中實(shí)現(xiàn)以上的預(yù)編譯功能 提升你的代碼在瀏覽器中的執(zhí)行速度。

    new webpack.optimize.ModuleConcatenationPlugin(),

    //把靜態(tài)資源copy

    new CopyWebpackPlugin([{

      from: path.resolve(__dirname, '../static'),

      to: '/static',

      ignore: ['.*']

    }]),

    process.env.NODE_ENV=== 'analysis' ? new BundleAnalyzerPlugin() : ()=>{}

  ]

})



// 需要服務(wù)端做相關(guān)的gzip配置

/*

gzip on;

gzip_disable "msie6";

gzip_buffers 32 4k;

gzip_static on;

 */

// 頁面請求后的Response Headers中的Content-Encoding的值為“gzip”酥泛,Request Headers中Accept-Encoding的值存在“gzip”值

if (true) {

  const CompressionWebpackPlugin = require('compression-webpack-plugin')



  webpackConfig.plugins.push(

    new CompressionWebpackPlugin({

      asset: '[path].gz[query]',

      algorithm: 'gzip',

      test: /\.(js|css)$/,

      threshold: 10240,

      minRatio: 0.8

    })
  )
}

module.exports = webpackConfig

utils.js

'use strict'

const path = require('path')

const autoprefixer = require('autoprefixer');

const packageConfig = require('../package.json')

const MiniCssExtractPlugin = require('mini-css-extract-plugin');





exports.cssLoaders = function (options) {

  options = options || {}

  // options是用來傳遞參數(shù)給loader的

  // minimize表示壓縮今豆,如果是生產(chǎn)環(huán)境就壓縮css代碼

  const cssLoader = {

    loader: 'css-loader',

    options: {

      sourceMap: options.sourceMap,

      importLoaders: 2,

      minimize: options.extract ? true : false,

    }

  }

  //postcss-loader

  const postcssLoader = {

    loader: 'postcss-loader',

    options: {

      sourceMap: options.sourceMap,

      plugins: () => [autoprefixer({

        browsers: 'last 5 versions'

      })],

    }

  }





  function generateLoaders (loader, loaderOptions) {

    // 將上面的基礎(chǔ)cssLoader配置放在一個(gè)數(shù)組里面

    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]

    // 如果該函數(shù)傳遞了單獨(dú)的loader就加到這個(gè)loaders數(shù)組里面,這個(gè)loader可能是less,sass之類的

    if (loader) {

      loaders.push({

        // 加載對應(yīng)的loader

        loader: loader + '-loader',

        // Object.assign是es6的方法柔袁,主要用來合并對象的呆躲,淺拷貝

        options: Object.assign({}, loaderOptions, {

          sourceMap: options.sourceMap

        })

      })

    }

    // 注意這個(gè)extract是自定義的屬性,

    //可以定義在options里面捶索,主要作用就是當(dāng)配置為true就把文件單獨(dú)提取插掂,false表示不單獨(dú)提取,

    if (options.extract) {

      return [ MiniCssExtractPlugin.loader ].concat(loaders)

    } else {

      return ['style-loader'].concat(loaders)

    }

  }



  return {

    css: generateLoaders(),

    postcss: generateLoaders(),

    less: generateLoaders('less', {

        modifyVars: {

            "@primary-color": "#075DA5",

            "@font-size-base": "12px",

            '@menu-dark-bg':'#283142'

        },

        javascriptEnabled: true,

    }),

    sass: generateLoaders('sass', { indentedSyntax: true }),

    scss: generateLoaders('sass'),

    stylus: generateLoaders('stylus'),

    styl: generateLoaders('stylus')

  }

}



// 下面這個(gè)主要處理import這種方式導(dǎo)入的文件類型的打包腥例,上面的exports.cssLoaders是為這一步服務(wù)的

exports.styleLoaders = function (options) {

  const output = []

  const loaders = exports.cssLoaders(options)

  // 下面就是生成的各種css文件的loader對象

  for (const extension in loaders) {

    // 把每一種文件的laoder都提取出來

    const loader = loaders[extension]

    // 把最終的結(jié)果都push到output數(shù)組中辅甥,大事搞定

    output.push({

      test: new RegExp('\\.' + extension + '$'),

      // exclude: /node_modules/,

      use: loader

    });

    // 處理node_modules中的樣式問題

    // if (options.extract === ) {

    //   output.push({

    //     test: new RegExp('\\.' + extension + '$'),

    //     include: /node_modules/,

    //     use: loader

    //   })

    // }

  }

  // console.log(output)

  return output

}



exports.createNotifierCallback = () => {

  const notifier = require('node-notifier')



  return (severity, errors) => {

    if (severity !== 'error') return

    const error = errors[0]

    const filename = error.file && error.file.split('!').pop()

    notifier.notify({

      title: packageConfig.name,

      message: severity + ': ' + error.name,

      subtitle: filename || '',

      icon: path.join(__dirname, 'logo.png')

    })
  }
}

至此一個(gè)基于webpack4+bable7的react腳手架就搭建完成了。

這樣的一個(gè)腳手架是不是維護(hù)起來特別方便和簡單呢燎竖?

附上GitHub地址

現(xiàn)在是webpack5了, 后面有時(shí)間給改成webpack5

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末璃弄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子构回,更是在濱河造成了極大的恐慌夏块,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捐凭,死亡現(xiàn)場離奇詭異拨扶,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)茁肠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缩举,“玉大人垦梆,你說我怎么就攤上這事匹颤。” “怎么了托猩?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵印蓖,是天一觀的道長。 經(jīng)常有香客問我京腥,道長赦肃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任公浪,我火速辦了婚禮他宛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘欠气。我一直安慰自己厅各,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布预柒。 她就那樣靜靜地躺著队塘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宜鸯。 梳的紋絲不亂的頭發(fā)上憔古,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機(jī)與錄音淋袖,去河邊找鬼鸿市。 笑死,一個(gè)胖子當(dāng)著我的面吹牛适贸,可吹牛的內(nèi)容都是我干的灸芳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼拜姿,長吁一口氣:“原來是場噩夢啊……” “哼烙样!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蕊肥,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤谒获,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后壁却,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體批狱,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年展东,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赔硫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盐肃,死狀恐怖爪膊,靈堂內(nèi)的尸體忽然破棺而出权悟,到底是詐尸還是另有隱情,我是刑警寧澤推盛,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布峦阁,位于F島的核電站,受9級特大地震影響耘成,放射性物質(zhì)發(fā)生泄漏榔昔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一瘪菌、第九天 我趴在偏房一處隱蔽的房頂上張望撒会。 院中可真熱鬧,春花似錦控嗜、人聲如沸茧彤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曾掂。三九已至,卻和暖如春壁顶,著一層夾襖步出監(jiān)牢的瞬間珠洗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工若专, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留许蓖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓调衰,卻偏偏與公主長得像膊爪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子嚎莉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

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