美文网首页VUE
从零搭建基于Webpack4的开发环境

从零搭建基于Webpack4的开发环境

作者: MrRuo | 来源:发表于2020-02-08 22:59 被阅读0次

    webpack是当前最流行的模块化,为了更好地理解和学习webpack,本文从零搭建基于webpack开发环境。

    代码地址

    项目初始化

    进入项目目录,生成package.json文件。因为我们并不是要做一个工具库,所以可以将main字段删除。main字段的主要作用是,通过import引入我们的程序,默认引入的具体文件。

    npm init -y
    
    // package.json
    {
      "name": "webpack-demo",
      "version": "1.0.0",
      "description": "",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    
    

    配置package.json执行文件

    运行npm run start之后,启动开发服务器,文件数据放在内存中,不会生成打包之后的dist文件。

    运行npm run build之后,执行打包命令,生成打包后的dist文件。

    // package.json
    {
      "name": "webpack-demo",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "start": "webpack-dev-server",
        "build": "webpack"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    运行命令之前,需要先配置webpack。

    安装webpack的依赖

    npm i webpack webpack-cli webpack-dev-server -D
    
    • 根目录下新建webpack.config.js文件, 该文件最终需要导出关于webpack的配置。可以是对象、函数或者Promise
    目录结构

    配置入口(entry)

    因为我们构建的是单页面应用,所以entry的值可以是字符串,直接写入入口文件的相对路径。

    // webpack.config.js
    module.exports = {
      entry: './src/main.js'
    }
    

    新建入口文件 /src/main.js

    目录结构

    entry的值也可以是对象,用来支持多页面应用的打包。我们在这里打包的是单页面应用,使用字符串的形式就足够了。

    // webpack.config.js
    module.exports = {
      entry: {
        home: "./home.js",
        about: "./about.js",
        contact: "./contact.js"
      }
    }
    

    配置出口(output)

    出口(ouput)决定了在什么位置输出、如何输出以及如何命名打包后的文件。

    filename中的[name]是入口文件名称的占位符,是entry是对象情况下的key,在entry是字符串的时候,[name]的值为main

    类似的展位符还有[id]内部chunk的id,[hash]唯一hash值以及[chunkhash]每个chunk内容生成的hash。

    output的参数还有很多,对于打包库文件比较有用的librarylibraryTarget,具体使用可以查阅文档

    // webpack.config.js
    const path = require('path');
    
    module.exports = {
      entry: './src/index.js',
      output: {
          filename: '[name].bundle.js',
          path: path.resolve('dist')
      }
    }
    

    配置mode

    mode告知webpack的打包环境是开发环境(development)还是生产环境(production)。可以根据不同的mode,运行不同的webpack配置。

    在这里我们用npm运行脚本的时候,通过NODE_ENV可以来设置环境变量。在webpack.config.js获取之后,进行设置。

    可以通过下面的形式对NODE_ENV进行设置。

    // mac & linux
    export NODE_ENV=production
    
    // window
    set NODE_ENV=production
    

    为了解决平台兼容性的问题,可以使用cross-env

    cnpm i cross-env -D
    

    并更改package.json

    // package.json
    {
      "name": "webpack-demo",
      "version": "1.0.0",
      "description": "",
      "scripts": {
        "start": "cross-env NODE_ENV=development && webpack-dev-server",
        "build": "cross-env NODE_ENV=production && webpack"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {...}
    }
    

    并在webpack.config.js中获取,并设置。

    // webpack.config.js
    
    ...
    
    const mode = process.env.NODE_ENV;
    
    module.exports = {
      entry: './src/main.js',
    
      ...
    
      mode
    }
    

    配置sourceMap

    sourceMap是一个源文件和打包之后文件的对应关系表。配置之前,所有的log信息的位置、行号都是对应打包之后的文件。只有配置之后,才能让log的信息显示正确的位置(源文件位置)。

    sourceMap有很多种类型,为了构建效率,开发环境下推荐使用cheap-module-eval-source-map,生产环境下可关闭。

    // webpack.config.js
    
    ...
    
    module.exports = {
      entry: './src/main.js',
      
      ...
    
      devtool: mode === 'development'
        ? 'cheap-module-eval-source-map'
        : 'none'
    }
    

    下面是从webpack官网截取的不同种类source map的分类图。

    source map

    配置loader

    • 配置babe-loader

    开发过程中,需要使用ES6的新特性提高开发效率。为了兼容低版本浏览器,需要引入babel将将ES6代码转换为低版本浏览器也能够识别的ES5代码。

    npm i babel-loader @babel/core core-js@3 regenerator-runtime  @babel/preset-env -D
    
    // webpack.config.js
    
    ...
    
    module.exports = {
      entry: './src/main.js',
      
      ...
    
      module: {
        rules: [
          { 
            test: /\.js$/, 
            exclude: /node_modules/, 
            loader: 'babel-loader',
          }
        ]
      }
    }
    
    

    根目录下新建.babelrc文件,并添加babel相关配置。

    目录结构
    // .babelrc
    {
      "presets": [
        [
          "@babel/preset-env", {
            "corejs": 3,
            "useBuiltIns": "usage"
          }
        ]
      ]
    }
    

    babel的编译功能是依赖于babel中的pluginpresetplugin的集合。

    我们在这里配置了presetbabel-preset-env用于ES6转ES5, preset的运行顺序是从下至上。如果我们要配置其他的preset一定要注意配置顺序。

    babel-preset-env中,useBuiltIns参数决定了babel如何处理pollyfill。值可以是usageentryfalse,默认是false。当设置useBuiltIns参数时(不为false),我们还需要引入core-js

    当使用useBuiltIns: "entry"时,在入口文件中一次性手动引入时,不推荐使用。

    当使用useBuiltIns:“usage”提取文件中所需的polyfill在每个文件引入,每种polyfill只会引入一次。

    package.json中配置browserslist,让babel编译成响应的版本。该配置对后面的postcss同样有效。

    // package.json
    {
      "name": "webpack-demo",
      
      ...
    
      "browserslist": [
        "iOS >= 7",
        "Android > 4.1"
      ]
    }
    
    

    后续的loader同样配置在module.rules中,和babel-loader同级。

    • 配置eslint

    eslint一个用来识别 ECMAScript 并且按照规则给出报告的代码检测工具。

    命令行输入npx eslint --init,按照提示进行安装。

    这样我们的eslint就安装好了,添加package.json的eslint代码检查命令。

    // package.json
    
    {
      "name": "webpack-demo",
      ...
      "scripts": {
        "start": "cross-env NODE_ENV=development webpack-dev-server",
        "build": "cross-env NODE_ENV=production webpack",
        "lint": "eslint src"
      },
      ...
    }
    
    

    在命令行中输入 npm run lint,就可以运行eslint检查代码了。为了更多的在webpack中使用eslint,需要安装eslint-loader

    npm i eslint-loader -D
    

    同时还要更改webpack.config.js

    // webpack.config.js
    
    ...
    
    module.exports = {
      entry: './src/main.js',
      
      ...
    
      module: {
        rules: [
          { 
            test: /\.js$/, 
            exclude: /node_modules/, 
            use: [ 'babel-loader', 'eslint-loader' ]
          }
        ]
      }
    }
    
    • 配置css相关的loader

    webpack如果要引入非js文件,需要引入相应的loader才能识别。

    除了必须的style-loadercss-loader之外,还引入了scss-loader来解析scss文件,以及postcss-loader帮助我们更好的管理css。

    npm i style-loader css-loader sass-loader node-sass postcss-loader autoprefixer -D
    

    根目录下新建postcss.config.js配置postcss,自动添加浏览器前缀,解决低版本浏览器的css兼容性问题。

    目录结构
    // postcss.config.js
    module.exports = {
      plugins: [
        require('autoprefixer')
      ]
    }
    
    // webpack.config.js
    
    ...
    
    {
      test: /\.scss$/,
      use: [
        'style-loader', 
        {
          loader: 'css-loader',
          options: {
            importLoaders: 2
          }
        },
        'sass-loader',
        'postcss-loader'
       ]
    },
    {
      test: /\.css$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 1,
          }
        },
       'postcss-loader'
      ]
    }
    
    ...
    
    
    • 配置图片相关的url-loader

    url-loader可以让小于指定大小的图片转换为Base64直接在页面中引入,大于指定大小的图片拷贝到目标文件夹。

    npm i url-loader -D
    
    // webpack.config.js
    
    ...
    
    {
      test: /\.(jpg|png|gif)$/,
      use: {
        loader: 'url-loader',
        options: {
          name: '[name]_[hash].[ext]',
          outputPath: 'images/',
          limit: 10240
        }
      } 
    }
    
    ...
    
    

    配置Plugin

    • clean-webpack-plugin

    每次打包之前,清楚原先的打包后的文件。

    cnpm i clean-webpack-plugin -D
    
    // webpack.config.js
    
    ...
    
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    
    module.exports = {
      entry: './src/main.js',
     
      ...
    
    
      plugins: [
        new CleanWebpackPlugin()
      ]
    }
    
    
    • html-webpack-plugin

    文件打包好之后,需要通过html引入,才能够在浏览器中渲染。

    html-webpack-plugintemplate参数指定了html模版位置。

    cnpm i html-webpack-plugin -D
    
    // webpack.config.js
    
    ...
    
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      entry: './src/main.js',
      
      ...
    
      plugins: [
        ...
        new HtmlWebpackPlugin({
          template: './src/index.html'
        })
      ]
    }
    
    • 启用 HMR

    启用 HMR之后,我们在更改代码时,只更改需要更改的组件,不会刷新页面,保留页面状态。

    webpack内置HMR相关插件,所以我们要引入webpack,并将HotModuleReplacementPlugin插件加入配置,完成对js的 HMR配置。

    不需要担心css文件,因为style-loader已经自动完成了。

    // webpack.config.js
    
    ...
    
    const webpack = require('webpack');
    
    module.exports = {
      entry: './src/main.js',
      ...
      plugins: [
        ...
        new webpack.HotModuleReplacementPlugin()
      ]
    }
    

    配置开发服务器

    // webpack.config.js
    
    ...
    
    module.exports = {
      entry: './src/main.js',
      ...
      devServer: {
        hot: true,   // 热更新
        open: true,  // 自动开启浏览器打开页面
        port: 8080   // 端口号
      }
    }
    
    

    配置解析(resolve)

    配置默认拓展名 resolve.extensions,不加后缀也可以通过impot引入到相应文件。
    配置目录别名resolve.alias,方便找到常用目录。

    // webpack.confgi.js
    
    ...
    
    module.exports = {
      entry: './src/main.js',
      ...
      resolve: {
        extensions: [ '.js', '.json' ],
        alias: {
          src: path.resolve(__dirname, 'src/')
        }
      }
    }
    
    

    配置优化(optimization)

    代码分割

    // webpack.config.js
    
    ...
    
    module.exports = {
      entry: './src/main.js',
      ...
      optimization: {
        splitChunks: {
          chunks: 'all'
        }
      }
    }
    

    相关文章

      网友评论

        本文标题:从零搭建基于Webpack4的开发环境

        本文链接:https://www.haomeiwen.com/subject/wsmixhtx.html