使用webpack4打造自己的前端工作流

栏目: 编程工具 · 发布时间: 6年前

内容简介:webpack4发布已经有一段时间了,我在实践的过程中发现,很多项目配置在webpack3下工作正常,但是升级到webpack4直接就崩了,如果想要webpack4正常工作,很多插件也需要升级到新版。下面是我使用webpack4配置的一个学习案例,包含了日常开发的常用配置项,比如多入口文件配置、模板文件自定义、版本号控制、js和css分离、css自动添加前缀、scss转css、图片及字体文件的处理、babel编译JS语法和API等等当我们修改代码后,需要重新打包文件,这时候为了避免浏览器缓存,往往需要为文

webpack4发布已经有一段时间了,我在实践的过程中发现,很多项目配置在webpack3下工作正常,但是升级到webpack4直接就崩了,如果想要webpack4正常工作,很多插件也需要升级到新版。下面是我使用webpack4配置的一个学习案例,包含了日常开发的常用配置项,比如多入口文件配置、模板文件自定义、版本号控制、js和css分离、css自动添加前缀、scss转css、图片及字体文件的处理、babel编译JS语法和API等等

版本号

当我们修改代码后,需要重新打包文件,这时候为了避免浏览器缓存,往往需要为文件添加一个版本号

var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js?[hash]'
  },
  plugins: [
    new HtmlWebpackPlugin({
      inject:'body', // 插入位置
      favicon: './favicon.ico', // icon图标
      title: 'webpack learn', // 生成的html文件的标题
      filename: 'index.html', // 生成的html文件名称
      minify:{
        removeComments: false, // 删除注释
        collapseWhitespace: false // 删除空格
      }
    })
  ]
}
复制代码

打包后的代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>webpack learn</title>
    <link rel="shortcut icon" href="favicon.ico">
  </head>
  <body>
  <script type="text/javascript" src="main.js?f8f60ca3f6ee44382620"></script></body>
</html>
复制代码

html-webpack-plugin这个插件会生成一个名为index.html、标题是 webpack learn 的文件,并且自动把打包后的文件插入到html中。如果不配置这个插件,filename的默认值就是 index.html ,title默认是 Webpack APP

inject表示插入的位置,默认是 body ,可选值 head favicon表示可以添加一个icon图标 minify表示对压缩文件,removeComments和collapseWhitespace的默认值都是false

模板文件

html-webpack-plugin插件可以使用模板文件,这样我们就可以自定义一个html文件,然后让这个插件把打包后的文件自动插入到模板文件中

tmp/tmp.html模板文件

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>template file</title>
  <body>
  <div>hello template</div>
</html>
复制代码

插件配置项

plugins: [
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: './tmp/tmp.html'
  })
]
复制代码

打包后生成的index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>template file</title>
  <body>
  <div>hello template</div>
</html>
<script type="text/javascript" src="main.js?b321307e65d6b0fbee0b"></script>
复制代码

多页面

对于多页面一般会对应多个入口文件,不同的html页面输出对应不同的入口文件,html-webpack-plugin插件支持配置多页面。多页面需要配置chunks和excludeChunks,chunks表示所包含的入口文件,excludeChunks表示要排除的入口文件

var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: {
    a: './src/main-a.js',
    b: './src/main-b.js',
    c: './src/main-c.js'
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js?[hash]'
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'a.html',
      template: './tmp/tmp.html',
      chunks: ['a'] // 加载a对应的打包文件
    }),
    new HtmlWebpackPlugin({
      filename: 'b.html',
      template: './tmp/tmp.html',
      chunks: ['b']  // // 加载b对应的打包文件
    }),
    new HtmlWebpackPlugin({
      filename: 'c.html',
      template: './tmp/tmp.html',
      excludeChunks: ['a', 'b'] // 加载非a、b对应的打包文件
    })
  ]
}
复制代码

运行结果

<!-- a.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>webpack learn</title>
  <body>
  <div>hello template</div>
</html>
<script type="text/javascript" src="a.js?82a9a04389852053c167"></script>

<!-- b.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>webpack learn</title>
  <body>
  <div>hello template</div>
</html>
<script type="text/javascript" src="b.js?82a9a04389852053c167"></script>

<!-- c.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>webpack learn</title>
  <body>
  <div>hello template</div>
</html>
<script type="text/javascript" src="c.js?82a9a04389852053c167"></script>
复制代码

内联

除了以链接的形式引入入口文件,也可以内联到页面中。html-webpack-inline-source-plugin插件专门用来处理入口文件内联的

var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js?[hash]'
  },
  plugins: [
    new HtmlWebpackPlugin({
      inlineSource: '.(js|css)$' // 所有的js和css文件内联引入
    }),
    new HtmlWebpackInlineSourcePlugin()
  ]
}
复制代码

babel

babel可以把es最新标准的代码转为es5代码,首先需要安装babel-core核心程序,及babel-loader

npm i babel-loader babel-core -D
复制代码

由于ES每年会发布一个新版本,所以在进行转换时,需要选择从哪个标准进行转换,可供选择的有'es2015'、'es2016'、'es2017'、'latest'、'env'等多个不同的标准。

babel-preset-env标准是使用最多的,babel-preset-env在没有任何配置选项的情况下,与 babel-preset-latest(或者babel-preset-es2015,babel-preset-es2016和babel-preset-es2017一起)的行为完全相同

npm i babel-preset-env  -D
复制代码
var webpack = require('webpack');
var path = require('path');
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js?[hash]'
  },
  module: {
    rules:[{
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['env'],
          cacheDirectory: true
        }
      }
    }]
  }
}
复制代码

rules属性中配置的exclude表示 node_modules 文件夹不需要babel进行转换。也可以配置一个include选项,比如 include: path.resolve(__dirname, 'src') ,表示只有src文件夹中的文件需要转换

cacheDirectory选项的默认值是false,设置为true将缓存 loader 的执行结果,加快编译速度

API转换

babel默认只转换JavaScript语法,对于新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等是不会转换的。如果需要转换API,需要使用babel-polyfill,babel-polyfill是一个全局垫片

npm i babel-polyfill -D
复制代码

入口文件引入babel-polyfill

// main.js
import 'babel-polyfill';
let set = new Set([1,2,3]);
复制代码

babel-polyfill是一个全局垫片,开发中更常用的是babel-plugin-transform-runtime这个局部垫片,因为它可以使包的体积更小

npm i babel-plugin-transform-runtime babel-runtime -D
复制代码
var webpack = require('webpack');
var path = require('path');
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js?[hash]'
  },
  module: {
    rules:[{
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['env'],
          cacheDirectory: true,
          plugins: ['transform-runtime']
        }
      }
    }]
  }
}
复制代码

CSS

处理css会用到css-loader和style-loader,css-loader用于读取并加载css文件,style-loader将它插入到页面中

// main.js
require('./assets/styles/cssdemo.css');
复制代码
var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js?[hash]'
  },
  module: {
    rules:[{
      test: /\.css$/,
      use: ['style-loader', 'css-loader']
    }]
  },
  plugins: [
    new HtmlWebpackPlugin({})
  ]
}
复制代码

自动前缀

由于各大浏览器对CSS兼容性不同,部分CSS特性需要加上浏览器前缀才能正常工作,postcss-loader可以帮我们自动完成加前缀的工作

npm i postcss-loader autoprefixer postcss-import -D
复制代码
module: {
  rules: [{
    test: /\.css$/,
    use: ['style-loader', {
        loader: 'css-loader',
        options: { importLoaders: 1 }
      },
      {
        loader: 'postcss-loader',
        options: {
          plugins: [
            require('postcss-import'), // 解决css中import其他css
            require('autoprefixer')
          ]
        }
      }
    ]
  }]
}
复制代码

sass

需要安装sass-loader及node-sass。

npm i sass-loader node-sass -D
复制代码
module: {
  rules: [{
    test: /\.scss$/,
    use: ['style-loader','css-loader',
      {
        loader: 'postcss-loader',
        options: { plugins: [require('autoprefixer')] }
      },
      'sass-loader'
    ]
  }]
}
复制代码

分离css

默认情况下,CSS会被打包到入口JS文件中。如果需要把CSS分离出来,需要使用extract-text-webpack-plugin插件

npm i extract-text-webpack-plugin@next -D
复制代码
var webpack = require('webpack');
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
  entry: './src/main.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js?[hash]'
  },
  module: {
    rules: [{
      test: /\.scss$/,
      use: ExtractTextPlugin.extract({
        fallback: 'style-loader',
        use: ['css-loader',
          {
            loader: 'postcss-loader',
            options: { plugins: [require('autoprefixer')] }
          },
          'sass-loader'
        ]
      })
    }]
  },
  plugins: [
    new HtmlWebpackPlugin({}),
    new ExtractTextPlugin('main.css')
  ]
}
复制代码

图片资源

webpack处理图片、字体、音乐、视频等资源时,需要安装file-loader

npm i file-loader -D
复制代码
// main.js
require('./assets/styles/cssdemo.css');
复制代码
/* cssdemo.css */
body {
  background: url('../images/dog.jpg') no-repeat;
}
h1 {
  color: red;
}
复制代码
module: {
  rules: [{
      test: /\.css$/,
      use: ['style-loader', 'css-loader']
    }, {
      test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
      loader: 'file-loader'
    },
    {
      test: /\.(png|jpe?g|gif|svg)(\?\S*)?$/,
      loader: 'file-loader',
      query: {
        name: '[name].[ext]?[hash]'
      }
    }
  ]
}
复制代码

如果是在html模板中,通过img标签引入图片,需要使用 ${require('')} 将相对路径包裹一次

<img src="${require('../src/images/dog.jpg')}" alt="">
复制代码

第三方库

比如说我们通过npm安装了jQuery,只需要通过provide-plugin插件就可以自动加载模块,而不必到处 import 或 require

npm i provide-plugin -D
复制代码
var ProvidePlugin = require('provide-plugin');

plugins: [
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery'
  })
]
复制代码

在项目中使用

console.log($('#box'), jQuery('#box'))
复制代码

如果是把jQuery保存到了本地,可以通过设置别名来引用

resolve:{
  alias:{
    jQuery$: path.resolve(__dirname,'src/libs/jquery.min.js')
  }
}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Concepts, Techniques, and Models of Computer Programming

Concepts, Techniques, and Models of Computer Programming

Peter Van Roy、Seif Haridi / The MIT Press / 2004-2-20 / USD 78.00

This innovative text presents computer programming as a unified discipline in a way that is both practical and scientifically sound. The book focuses on techniques of lasting value and explains them p......一起来看看 《Concepts, Techniques, and Models of Computer Programming》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

html转js在线工具
html转js在线工具

html转js在线工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试