从0开始搭建vue+webpack脚手架(四)

之前1-3部分是webpack最基本的配置, 接下来会把项目结构和配置文件重新设计,可以扩充更多的功能模块。

一、重构webpack的配置项

1. 新建目录build,存放webpack不同的配置文件

  (1) webpack.config.base.js  【保留公共的配置项,将生产环境和开发环境使用的配置项分离出去】

 1 const path = require('path')
 2 const webpack = require('webpack')
 3 const VueLoaderPlugin = require('vue-loader/lib/plugin')
 4 const HtmlWebpackPlugin = require('html-webpack-plugin')
 5 const CleanWebpackPlugin = require('clean-webpack-plugin')
 6 
 7 const isDev = process.env.NODE_ENV === 'development'
 8 
 9 const config = {
   mode: process.env.NODE_ENV || 'production'
10 target: 'web', 11 performance: { 12 hints: false, 13 maxAssetSize: 500000 14 }, 15 entry: path.join(__dirname, '../src/index.js'), 16 output: { 17 path: path.join(__dirname, '../dist'), 18 filename: 'scripts/bundle.[hash:8].js' 19 }, 20 module: { 21 rules: [ 22 { 23 test: /\.vue$/, 24 use: [ 25 { 26 loader: "vue-loader" 27 } 28 ] 29 }, 30 { 31 test: /\.jsx$/, 32 loader: "babel-loader" 33 }, 34 { 35 test: /\.js$/, 36 loader: "babel-loader", 37 exclude: /node_modules/ 38 }, 39 { 40 test: /\.(jpg|jpeg|gif|png|svg)$/, 41 use: [ 42 { 43 loader: "url-loader", 44 options: { 45 limit: 1024, 46 name: 'images/[name]-[hash:8].[ext]' 47 } 48 } 49 ] 50 } 51 ] 52 }, 53 plugins: [ 54 new VueLoaderPlugin() 55 ] 56 } 57 58 module.exports = config

注意: 入口文件和输出路径

注意: VueLoaderPlugin是使用vue-loader必须的,两种环境都需要加载。jsx和js的规则分开配置,因为js编译时需要除去node_modules目录下的文件。

  (2) webpack.config.client.js 【配置开发和生产环境环境需要的选项】

    安装 webpack-merge工具, 提供配置文件扩展方法。

1 $ npm i -D webpack-merge

    (3)  在webpack.config.client.js中使用merge对基础的配置baseConfig进行扩展。

  1 const path = require('path')
  2 const webpack = require('webpack')
  3 const merge = require('webpack-merge')
  4 const VueLoaderPlugin = require('vue-loader/lib/plugin')
  5 const HtmlWebpackPlugin = require('html-webpack-plugin')
  6 const CleanWebpackPlugin = require('clean-webpack-plugin')
  7 const ExtractTextPlugin = require('extract-text-webpack-plugin')
  8 const baseConfig = require('./webpack.config.base')
  9 
 10 const isDev = process.env.NODE_ENV === 'development'
 11 const basePlugin = [
 12   new VueLoaderPlugin(),
 13   new CleanWebpackPlugin(['../dist']),
 14   // 根据不同环境区分打包
 15   new webpack.DefinePlugin({
 16     'process.env': {
 17       NODE_ENV: isDev ? '"development"' : '"production"',
 18     }
 19   }),
 20   new HtmlWebpackPlugin({
 21     template: path.join(__dirname, '../index.html')
 22   })
 23 ]
 24 const devServer = {
 25   port: 9000,
 26   host: '0.0.0.0',
 27   overlay: {
 28     errors: true
 29   },
 30   historyApiFallback: true,
 31   hot: true,
 32 }
 33 
 34 let config
 35 
 36 if (isDev) {
 37   config = merge(baseConfig, {
 38     // mode: 'development',
 39     // devtool: '#cheap-module-eval-source-map',
 40     module: {
 41       rules: [
 42         {
 43           test: /\.css$/,
 44           use: ['style-loader', 'css-loader']
 45         },
 46         {
 47           test: /\.styl(us)?$/,
 48           use: [
 49             'style-loader',
 50             'css-loader',
 51             {
 52               loader: "postcss-loader",
 53               options: {
 54                 sourceMap: true
 55               }
 56             },
 57             'stylus-loader',
 58           ]
 59         },
 60       ]
 61     },
 62     devServer,
 63     plugins: basePlugin.concat([
 64       new webpack.HotModuleReplacementPlugin(),
 65       new webpack.SourceMapDevToolPlugin() // devtool
 66     ])
 67   })
 68 } else {
 69   config = merge(baseConfig, {
 70     // mode: 'production',
 71     entry: {
 72       app: path.join(__dirname, '../src/index.js'),
 73       vendor: ['vue']
 74     },
 75     output: {
 76       filename: 'scripts/[name].[chunkhash:8].js'
 77     },
 78     module: {
 79       rules: [
 80         {
 81           test: /\.css$/,
 82           use: ExtractTextPlugin.extract({
 83             fallback: 'style-loader',
 84             use: ['css-loader']
 85           })
 86         },
 87         {
 88           test: /\.styl(us)?$/,
 89           use: ExtractTextPlugin.extract({
 90             fallback: 'style-loader',
 91             use: [
 92               'css-loader',
 93               {
 94                 loader: "postcss-loader",
 95                 options: {
 96                   sourceMap: true
 97                 }
 98               },
 99               'stylus-loader',
100             ]
101           })
102         },
103       ]
104     },
105     plugins: basePlugin.concat([
106       new ExtractTextPlugin('style.[hash:8].css'),
107     ]),
108     optimization: {
109       splitChunks: {
110         chunks: 'all'  // name: 'vendor'
111       },
112       runtimeChunk: true 115     }
116   })
117 }
118 
119 module.exports = config

注意红色部分的修改:

  1 .引入merge工具 和 webpack.config.base.js

  2 .将公共plugin提取保存在变量 basePlugin, 不在base.js中使用的原因是后续的服务端渲染时无需使用, 故只在生产环境和开发环境引用。

  3. 将devServer提取保存在变量中。

  4. 声明变量config, 保存通过merge以baseConfig为基础扩展的配置项

  5. basePlugin.concat()将公共的plugin添加到不同环境

修改package.json的运行脚本

1 "scripts": {
2     "test": "echo \"Error: no test specified\" && exit 1",
3     "build": "cross-env NODE_ENV=production webpack --config build/webpack.config.client.js --colors --progress",
4     "dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.client.js --colors --progress",
5     "start": "npm run dev"
6 },

注意, 指向指定路劲时必须使用 --config否则报错无法编译。之前不用--config是因为默认指向了根目录的webpack.config.js

至此: 运行 $ npm run build $ npm run dev正常。

另注: 如果后续需要编写服务端的代码,可以将项目分为client/ 和 server/ 两个目录,分别存放服务端和客户端的业务代码, 如下

将原来的src/改成client/ 注意别忘了修改 webpack.config.base.js和 webpack.config.client.js内的相关路径。目录修改根据自己的习惯和环境而定。

二、使用rimraf工具 ,在打包前删除旧包

  1. 之前使用的是clean-webpack-plugin,rimraf也有同样的功能,但rimraf可以直接写在scripts脚本内

  2. 安装 $ npm i -D rimraf

  3 . 添加到 scripts中

1 "scripts": {
2     "test": "echo \"Error: no test specified\" && exit 1",
3     "build": "npm run clean && cross-env NODE_ENV=production webpack --config build/webpack.config.client.js --colors --progress",
4     "dev": "npm run clean && cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.client.js --colors --progress",
5     "start": "npm run clean && npm run dev",
6     "clean": "rimraf dist"
7 },

三、添加eslint代码校验

  (1)安装eslint及其依赖

npm i -D eslint 
npm i -D eslint-config-standard eslint-plugin-standard 
npm i -D eslint-plugin-promise eslint-plugin-import eslint-plugin-node
npm i -D eslint-plugin-html

  特别要说明的是,在vue项目中,eslint默认是无法解析.vue的文件, 所以需要使用 eslint-plugin-html插件来解析 , 其他都是辅助eslint的插件和工具 

(2)创建 .eslinrc配置文件

{
  "extends": "standard",
  "plugins": [
    "html"
  ]
}

 (3)package.json中添加命令

1 "scripts": {
2     "test": "echo \"Error: no test specified\" && exit 1",
3     "build": "npm run clean && cross-env NODE_ENV=production webpack --config build/webpack.config.client.js --colors --progress",
4     "dev": "npm run clean && cross-env NODE_ENV=development webpack-dev-server --config build/webpack.config.client.js --colors --progress",
5     "lint": "eslint --ext .js --ext .jsx --ext .vue client/",
6     "fix": "eslint --fix --ext .js --ext .jsx --ext .vue client/",
7     "start": "npm run clean && npm run dev",
8     "clean": "rimraf dist"
9 },

配置完成后运行脚本 : $ npm run lint会提示出一系列的警告。这是因为之前编写的代码中有些不符合eslint的默认规范。 可以使用 $ npm run  fix命令批量修复。

  (4)错误

  在新版本的eslint中,如果设置extends为 'standard'则会报错:(不再支持"standard"的方式, 具体原因暂时未知),将eslinrc修改如下

 1 module.exports = {
 2   "env": {
 3     "browser": true,
 4     "commonjs": true,
 5     "es6": true
 6   },
 7   "extends": ["eslint:recommended"],
 8   "plugins": [
 9     "html"
10   ]
11 }

运行 $ npm run lint 但又出现错误:都不能使用export和 import, 继续添加配置

1 "parserOptions": {
2     "ecmaFeatures": {
3       "jsx": true
4     },
5     "ecmaVersion": 2015,
6     "sourceType": "module"
7 },

此时运行 $ npm run lint不再报错。

以上是使用 eslint-plugin-html 解析vue文件 , 也可以使用插件 eslint-plugin-vue来解析vue 文件,安装插件后修改eslintrc

1 "extends": ["eslint:recommended", "plugin:vue/essential"],
2   "plugins": [
3     "vue"
4  ],

运行 $ npm run lint检查错误, 运行 $ npm run fix修正错误。

  (5)在webpack项目中使用eslint-loader

   安装 

1 $ npm i -D eslint-loader
2 $ npm i -D babel-eslint

    eslintrc的 parserOptions 中添加 babel-eslint

1 "parserOptions": {
2     "parser": "babel-eslint",   // 解析检测babel的代码
3     "ecmaFeatures": {    
4       "jsx": true          // 检测jsx语法
5     },  
6     "ecmaVersion": 2015,
7     "sourceType": "module" 
8  },

    在 webpack.config.base.js中 rules 添加 eslint 规则

1 {
2    test: /\.(vue|js|jsx)$/,
3    exclude: /node_modules/,
4    loader: "eslint-loader",
5    enforce: "pre"   // 预处理,在匹配的文件编译前先检测语法
6 },

至此, 运行项目, 并在业务文件内改成有错误的格式, eslint将会自动检测到后提示错误, 只要再修改回来即可正常。

接下来在 eslintrc文件中配置 rules,设置指定的语法格式。这里只配置了一小部分,根据项目需求可自定义。

"rules": {
    "no-new": "off",
    "no-alert": "off",
    "no-console": [
      "off"
    ],
    "eol-last": 0,
    "space-before-function-paren": 0,
    "indent": 0
  }

 0 或者 off一般表示关闭不做解析。如以上代码中"indent" :0表示不做缩进的检测, "indent": 2 表示缩进是两个空格否则会报错, 其他用法可参考官网。

  

猜你喜欢

转载自www.cnblogs.com/hughes5135/p/9336777.html