使用 webpack 搭建 vue 开发环境(二)

使用 webpack 搭建 vue 开发环境(二)

接着上一回,第二篇文章开始更进一步的配置

老规矩,基于 v0.0.1 的代码继续开发,这次配置结束后的代码将会划分为 v0.0.2

使用 less 完善开发体验

安装使用 css 预处理器-less

npm install --save-dev less less-loader

修改配置,因为 test 是可以接收正则表达式的,那么对于 cssless的匹配,我们可以这样写:test: /\.(less|css)$/,

  • webpack.base.js

修改原先的 test:/\.css$/ 的模块

module.exports = {
    
    
  // ...
  module: {
    
    
    rules: [
      {
    
    
        test: /\.(less|css)$/,
        use: ['vue-style-loader', {
    
     loader: 'css-loader', options: {
    
     esModule: false } }, 'less-loader']
      }
    ]
  }
  // ...
}

配置完成后,回到App.vue。我们在 style 标签上补上 lang="less" 。并且根据 less 语法写一写

  • App.vue
<style lang="less">
  .text-red {
     
     
    color: #000;
  }

  .avatar {
     
     
    width: 100px;
    height: 100px;
    &.bg-avatar {
     
     
      background-image: url('./assets/image/avatar.jpg');
      background-size: 100% 100%;
      background-repeat: no-repeat;
    }
  }
</style>

也可以新建一个 /src/assets/css/common.less 文件,试下 @import 引入的功能

  • /src/assets/css/common.less
body {
  background-color: #909090;
}
  • App.vue
<style lang="less">
  @import './assets/css/common.less';
  .text-red {
     
     
    color: #000;
  }

  .avatar {
     
     
    width: 100px;
    height: 100px;
    &.bg-avatar {
     
     
      background-image: url('./assets/image/avatar.jpg');
      background-size: 100% 100%;
      background-repeat: no-repeat;
    }
  }
</style>

可以看到都生效了,因为之前的 url-loader。所以我们在引入文件的时候也是顺顺利利的~

配置 css 前缀自动补全

各大浏览器有不同的前缀。自己一个个敲实在是太痛苦了,你能想象到 border-raidus 也会有兼容前缀吗(虽然现在是个浏览器都支持)

要想打包自动加前缀,就要用到 postcss-loader,和autoprefixer

npm i autoprefixer postcss-loader -D

配置之前,先说几个踩坑的地方,如果配置了 postcss-loader 和 autoprefixer 无效,可以留意下:

  • 配置 Autoprefixer 之前,需要先添加 Browserslist。可以在根目录加一个.browserslistrc 文件,也可以在package.json 文件中添加:browserslist不过一定要加,不然 autoprefixer 不生效

  • 其次,必须在根目录创建一个 postcss.config.js 后面会说到

  • autoprefixer 版本处理

  • webpack.base.js

根据 loader 从右往左的执行顺序 ,我们把 postcss-loader 安排在倒数第二位。

module.exports = {
    
    
  // ...
  module: {
    
    
    rules: [
      {
    
    
        test: /\.(less|css)$/,
        use: [
          'vue-style-loader',
          {
    
     loader: 'css-loader', options: {
    
     esModule: false } },
          'postcss-loader',
          'less-loader'
        ]
      }
    ]
  }
  // ...
}
  • package.json
    我就不多加文件了,直接在 package.json 完成这段配置
{
    
    
  "browserslist": ["last 2 version", "> 1%", "iOS >= 7", "Android > 4.1", "Firefox > 20"]
}
  • 根目录添加文件 postcss.config.js
module.exports = {
    
    
  plugins: [require('autoprefixer')]
}

为什么需要单独创建 postcss.config.js ,不能写 webpack 配置里面吗?

经过测试,postcss.config.js 存在的目的是因为 webpack 中的 postcss-loader 已经不支持写 plugins 了。所以需要额外的文件进行配置。

configuration has an unknown property 'rules'. These properties are valid:
   object { amd?, bail?, cache?, context?, dependencies?, devServer?, devtool?, entry?, externals?, infrastrdule?, name?, node?, optimization?, output?, parallelism?, performance?, plugins?, profile?, recordsInputPath?, resolve?, resolveLoader?, serve?, stats?, target?, watch?, watchOptions? }

添加需要加前缀的 css 测试下,最简单的就是 display:flex;。看下效果

为啥呢,因为自动安装的 autoprefixer 版本太高了,我装的是 "autoprefixer": "^10.0.0"
具体可以看下这个 issues

接下来对 autoprefixer 一个降级处理

npm uninstall autoprefixer

npm install [email protected] -D

最后运行也是自动不全了前缀

配置 css 样式分离

重点:在开始使用 css 样式和 JS 分离之前,需要一定非常的清楚 publicPath 中 / 和 ./ 的区别!!
如果不了解 publicPath 的作用,可以先看这部分:webpack/vue-cli 中的 publicPath 区别

搞了那么久,css 的前缀总算是 OK 了,那打包看下效果如何
不打包都没发现,原来 css 都混杂在了 JS 里面,这也意味着原来就很大的 JS 文件,现在更加是雪上加霜,万一页面样式足够复杂,那真是不敢相信

接下来就用到 mini-css-extract-plugin 配置 css 分离和压缩

npm i mini-css-extract-plugin -D
  • webpack.base.js

还是改 css 的模块,这次把 vue-style-loader 去掉了
而且 css 输出文件夹配置了非根目录的情况,需要配置 publicPath 。根据之前说的 webpack/vue-cli 中的 publicPath 区别 我就在开发环境下用 / 。在生产环境中用 ../MiniCssExtractPlugin.loader 也单独配置 publicPath 为 ../。不知道为啥的记得看之前的链接~

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
    
    
  output: {
    
    
    filename: '[name].[contenthash].js',
    publicPath: './', // base.js 中的这个配置其实会被后面覆盖掉,所以写哪个都没关系
    path: path.resolve(ROOT_PATH, 'dist')
  },
  module: {
    
    
    rules: [
      // ...
      {
    
    
        test: /\.(less|css)$/,
        use: [
          {
    
    
            loader: MiniCssExtractPlugin.loader,
            options: {
    
    
              publicPath: '../' // 注意添加了输出路径
            }
          },
          {
    
     loader: 'css-loader', options: {
    
     esModule: false } },
          'postcss-loader',
          'less-loader'
        ]
      }
    ]
  },
  plugins: [
    // ...
    new MiniCssExtractPlugin({
    
    
      // css的分离到了单独的 css 目录下,并且哈希值继续使用 contenthash
      filename: 'css/[name].[contenthash:4].css'
    })
  ]
}
  • webpack.dev.js
const baseConfig = require('./webpack.base')
const {
    
     merge } = require('webpack-merge')
const path = require('path')
const ROOT_PATH = path.resolve(__dirname, '../')

module.exports = merge(baseConfig, {
    
    
  mode: 'development',
  output: {
    
    
    filename: '[name].[contenthash].js',
    publicPath: '/', // dev 环境下记得使用 / 不然会有其他问题
    path: path.resolve(ROOT_PATH, 'dist')
  }
})
  • webpack.prod.js
const baseConfig = require('./webpack.base')
const {
    
     merge } = require('webpack-merge')
const {
    
     CleanWebpackPlugin } = require('clean-webpack-plugin')
const path = require('path')
const ROOT_PATH = path.resolve(__dirname, '../')

module.exports = merge(baseConfig, {
    
    
  mode: 'production',
  output: {
    
    
    filename: '[name].[contenthash].js',
    publicPath: './', // prod 的配置和dev目前是差不多的,不过 publicPath 换成了 './'
    path: path.resolve(ROOT_PATH, 'dist')
  },
  // 而且还多了一个打包清空dist的插件
  plugins: [new CleanWebpackPlugin()]
})

运行起来看下效果,css 中的图片前缀已经补全了 ../ ,看来已经生效了

最后还是非常强调 对 publicPath 配置的理解,自己动手写 webpack 好处就是自己清楚每个工作的流程嘛!

使用babel把 ES6 转 ES5

现在 vue 环境也有了,less 也装上了(saas 大同小异,有空在补一个插件配置把),然后 css 自动补全也没问题,文件分离的坑也踩过了,

but 漏掉最重要的问题 —— 让我们打开 IE 浏览器:

出现这个问题也是见怪不怪了,JS 语法也得往低兼容,babel 这个都不陌生把

安装 babel-loader ,不过这个插件呢也依赖了其他插件:@babel/core,@babel/plugin-transform-runtime,@babel/preset-env

npm i babel-loader @babel/core @babel/plugin-transform-runtime @babel/preset-env -D
  • webpack.base.js

添加一下转换,排除 node_modules 的包

module.exports = {
    
    
  module: {
    
    
    rules: [
      // ...
      {
    
    
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
    
    
          loader: 'babel-loader',
          options: {
    
    
            presets: ['@babel/preset-env'],
            plugins: ['@babel/plugin-transform-runtime']
          }
        }
      }
    ]
  }
  // ...
}

然后重新运行项目,到 IE 看看情况: 冇得问题

打包,然后用 http-serve 运行看看(主要想验证下打包会不会出 bug),记得要用 http-serve。不然预览不了

js 的语法转化也 OK 了。看来写配置越来越顺利了!

整理项目资源

在 v0.0.2 收官之前,重新看下我们写的配置:webpack-base.js,webpack-dev.js,webpack-prod.js。公共的地方有啥:

2 个公共目录

  • ROOT_PATH
  • path.resolve(ROOT_PATH, ‘dist’)

这一块也是先做一个迁移,写一个公共的配置文件把,这样不论配置文件走到哪里,目录基本都不会乱

build 文件夹下新建一个PATH.js,存放我们项目要用的常用的目录

整理了几个文件夹,打包后的 dist 文件目录,还有模版文件的 index.html 文件,入口文件等,整理这部分也是为后面的多入口页面做铺垫了

  • build/PATH.js
const path = require('path')
const ROOT = path.resolve(__dirname, '../')
const DIST = path.resolve(ROOT, 'dist')

const tmp_main = path.resolve(ROOT, 'src/main.js')
const TEMPLATE_HTML = path.resolve(ROOT, 'public/index.html')

module.exports = {
    
    
  ROOT,
  DIST,
  TEMPLATE_HTML,
  tmp_main
}
  • webpack.base.js
// 注意2个地方被注释掉了,统一从PATH引入
// const path = require('path')
// const ROOT_PATH = path.resolve(__dirname, '../')
const {
    
     DIST, tmp_main, TEMPLATE_HTML } = require('./PATH')

module.exports = {
    
    
  output: {
    
    
    filename: '[name].[contenthash].js',
    publicPath: './',
    path: DIST // 改动了这里的PATH
  },
  // ...
  plugins: [
    // ...
    // 设置html模板生成路径
    new HtmlWebpackPlugins({
    
    
      filename: 'index.html',
      template: TEMPLATE_HTML, // 改了 template 的目录
      chunks: ['main'] // 指定在html自动引入的js打包文件
    })
  ]
}
  • webpack-dev.js 和 webpack-prod.js
    2 个文件改动地方也是一样的了,就不重复写了
// 注意2个地方被注释掉了,统一从PATH引入
// const path = require('path')
// const ROOT_PATH = path.resolve(__dirname, '../')
const {
    
     DIST } = require('./PATH')

// output.path 改一下为 DIST 就可以了

最后

webpack 踩坑系列(二)也算是结束了~。介绍了使用 less,css 的样式分离,css 前缀补全,为了兼容 IE 老大哥做的 JS 转换

变动文件如下:



不过现在项目还是打包了一个页面,而我的想法是做一个 多入口的单页面应用。做的可能没 nuxt 那么厉害那么复杂,不过在一定意义上可以减少首屏加载的问题~

下期预告:

  • 当前项目的热更新是属于哪种热更新?
  • 实现一个简单的多入口
  • 实现自动获取入口(重头戏)
  • 添加代码运行后的URL输出

我的原文博客地址,点一下提高一下SEO收录,感谢感谢~ 使用 webpack 搭建 vue 开发环境(二)

猜你喜欢

转载自blog.csdn.net/Jioho_chen/article/details/108826627