vue

wepack从0开始配置vue环境之一: 基础配置

2018-04-05  本文已影响136人  胖太_91bf

github传送门 dev分支
webpack之二webpack部署优化
webpack之三集成vuex和vue-Router
webpack之四集成ssr

// cd到项目目录
cnpm init -y

生成package.json文件

cnpm i webpack vue-loader webpack@3 -D
cnpm i vue -S
// 安装完成根据warning安装需要的依赖
css-loader vue-template-compiler -D
<template>
  <div class="text">{{text}}</div>
</template>
<script>
export default {
  data () {
    return {
      text: 'abc'
    }
  }
}
</script>
<style>
  .text {
    color: red;
  }
</style>
 const path = require('path')

module.exports = {
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.vue$/, 
        loader: 'vue-loader'
      }
    ]
  }
}
import Vue from 'vue'
import App from './app.vue'

const root = document.createElement('div')
document.body.appendChild(root)

new Vue({
  render: h => h(App)
}).$mount(root)
cnpm i style-loader url-loader file-loader -D
url-loader依赖于file-loader
module: {
    rules: [
      {
        test: /\.vue$/, 
        loader: 'vue-loader'
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(jpg|png|svg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: '[name]-kay.[ext]'
            }
          }
        ]
      }
    ]
  }
cnpm i rimraf -D
//在package.json.script中添加cli
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "npm run clean && webpack --config webpack.config.js",
    "clean": "rimraf dist"
  },
cnpm i stylus stylus-loader -D
{
    test: /\.styl$/,
      use: [
        'style-loader',
        'css-loader',
        'stylus-loader'
      ]
},

安装cross-env区分开发环境和生产环境
配置html模板html-webpack-plugin
配置webpack全局常量插件webpack.DefinePlugin()
变更webpack.config.js结构
在package.json.script里添加dev命令

cnpm i webpac-dev-server@2 cross-env 
 -D
cnpm i html-webpack-plugin -D
//package.json.script
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"

// 代码
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

const isDev = process.env.NODE_ENV === 'development'

const config = {
  target: 'web',
  resolve: {
    alias: {
      '@assets':path.join(__dirname, 'src/assets')
    }
  },
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.vue$/, 
        loader: 'vue-loader'
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.styl$/,
        use: [
          'style-loader',
          'css-loader',
          'stylus-loader'
        ]
      },
      {
        test: /\.(jpg|png|svg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: '[name]-kay.[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: isDev ? '"development"' : '"production"'
      }
    }),
    new HtmlWebpackPlugin()
  ]
}

if (isDev) {
  config.devServer = {
    port: 8001,
    host: '0.0.0.0',
    overlay: {
      errors: true
    }
  }
}

module.exports = config
// 终端输入 npm run dev启动项目

使用webpack.HotModuleReplacementPlugin和webpack.NoEmitOnErrorsPlugin
配置devServer.hot = true
css热更替使用vue-style-loader代替style-loader

if (isDev) {
  config.devServer = {
    port: 8001,
    host: '0.0.0.0',
    overlay: {
      errors: true
    },
    hot: true
  }
  config.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
  )
}
config.devtool = '#cheap-module-eval-source-map'
// .babelrc
{
  "presets":[
    "env"
  ],
  "plugins": [
    "transform-vue-jsx"
  ]
}
// postcss.config.js
const autoprefixer = require('autoprefixer')
module.exports = {
  plugins: [
    autoprefixer()
  ]
}
// 在devServer里添加babel-loader和postcss-loader
{
        test: /\.js$/,
        loader: 'babel-loader'
      },
      {
        test: /\.jsx$/,
        loader: 'babel-loader'
      },
{
        test: /\.styl$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true
            }
          },
          'stylus-loader'
        ]
      },

新建/src/views/test.jsx

export default {
  data () {
    return {
      test: '这是用jsx语法写的vue模板'
    }
  },
  render () {
    return (
      <div>
        {this.test}
      </div>
    )
  }
}

使用extract-text-webpack-plugin
分离打包需要区分环境,删除config目录上的stylus-loader, 并在对应环境下对应loader配置
/webpack.config.js重写后配置如下

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtartTextPlugin = require('extract-text-webpack-plugin')

const isDev = process.env.NODE_ENV === 'development'

const config = {
  target: 'web',
  resolve: {
    alias: {
      '@assets':path.join(__dirname, 'src/assets')
    }
  },
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.vue$/, 
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.jsx$/,
        loader: 'babel-loader'
      },
      {
        test: /\.(jpg|png|svg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: '[name]-kay.[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: isDev ? '"development"' : '"production"'
      }
    }),
    new HtmlWebpackPlugin()
  ]
}

if (isDev) {
  config.module.rules.push({
    test: /\.styl$/,
    use: [
      'style-loader',
      'css-loader',
      {
        loader: 'postcss-loader',
        options: {
          sourceMap: true
        }
      },
      'stylus-loader'
    ]
  })
  config.devtool = '#cheap-module-eval-source-map'
  config.devServer = {
    port: 8001,
    host: '0.0.0.0',
    overlay: {
      errors: true
    },
    hot: true
  }
  config.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
  )
} else {
  config.module.rules.push({
    test: /\.styl$/,
    use: ExtartTextPlugin.extract({
      fallback: "style-loader",
      use: [
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            sourceMap: true
          }
        },
        'stylus-loader'
      ]
    })
  })
  config.plugins.push(
    new ExtartTextPlugin({
      filename: 'style.[contenthash:8].css'
    })
  )
}

module.exports = config

修改线上环境entry选项使用options模式为js文件添加name属性app和vendor -> 是output中[name]的由来,将开发环境的output.filename修改为'bundle.[hash:8].js',
正式环境修改为: '[name].[chunkhash:8].js'(不可以使用hash, webpack-dev-server会报错)
hash和chunkhash的区别:使用hash会让app和vendor的hash码一样是整个应用的hash(如果某个js文件改变了, 说有js文件的hash也会跟着改变, 正式环境就 没有意义了), 而chunkhash是每一个模块或者说节点单独生成hash,
使用
webpack.optimize.CommonsChunkPlugin({name: 'vendor'})
单独打包webpack相关的js代码:(好处是在有新的模块加入时候, webpack会给模块加id, 如果在中间插入会改变之前代码的id, 这样会导致hash变化破坏缓存, 需要单独打包)vendor必须在runtime之前
使用webpack.optimizeCommonsChunkPlugin({name: 'runtime'})
/webpack.config.js修改为:

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtartTextPlugin = require('extract-text-webpack-plugin')

const isDev = process.env.NODE_ENV === 'development'

const config = {
  target: 'web',
  resolve: {
    alias: {
      '@assets':path.join(__dirname, 'src/assets')
    }
  },
  entry: path.join(__dirname, 'src/index.js'),
  output: {
    filename: 'bundle.[hash:8].js',
    path: path.join(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.vue$/, 
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.jsx$/,
        loader: 'babel-loader'
      },
      {
        test: /\.(jpg|png|svg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: '[name]-kay.[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: isDev ? '"development"' : '"production"'
      }
    }),
    new HtmlWebpackPlugin()
  ]
}

if (isDev) {
  config.module.rules.push({
    test: /\.styl$/,
    use: [
      'style-loader',
      'css-loader',
      {
        loader: 'postcss-loader',
        options: {
          sourceMap: true
        }
      },
      'stylus-loader'
    ]
  })
  config.devtool = '#cheap-module-eval-source-map'
  config.devServer = {
    port: 8001,
    host: '0.0.0.0',
    overlay: {
      errors: true
    },
    hot: true
  }
  config.plugins.push(
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
  )
} else {
  config.entry = {
    app: path.join(__dirname, 'src/index.js'),
    vendor: ['vue']
  }
  config.output.filename = '[name].[chunkhash:8].js'
  config.module.rules.push({
    test: /\.styl$/,
    use: ExtartTextPlugin.extract({
      fallback: "style-loader",
      use: [
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            sourceMap: true
          }
        },
        'stylus-loader'
      ]
    })
  })
  config.plugins.push(
    new ExtartTextPlugin({
      filename: 'style.[contenthash:8].css'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'runtime'
    })
  )
}

module.exports = config

使用webpack.optimize.UglifyJsPlugin()并配置options.compress.warnings = false, options.output.comments: false

if(isDev) {
  ...
} else {
  ...
config.plugins.push(
    new ExtartTextPlugin({
      filename: 'style.[contenthash:8].css'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'runtime'
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      output: {
        comments: false
      }
    })
  )
}
  1. 安装optimize-css-assets-webpack-plugin@3
  2. 配置生成环境插件
new OptimizeCssAssetsPlugin({
        assetNameRegExp: /\.css$/,
        cssProcessor: require('cssnano'),
        cssProcessorOptions: { discardComments: { removeAll: true } },
        canPrint: true
      })

这一份简单webpack配置, 可以让vue跑起来, 但是远远不够, 接下来还会更新, 能够部署上线的配置和ssr服务器端渲染的配置
wepack从0开始配置vue环境之二: 线上部署配置优化
github地址可以下载源码来研究

上一篇下一篇

猜你喜欢

热点阅读