从零开始,配置webpack4

webpack版本:4.8.3
webpack-cli版本:2.1.3
1.全局安装webpack和webpack-cli
cnpm i webpack webpack-cli -g
2.新建一个项目, 然后初始化
cnpm init
然后会生成一个package.json和 package-lock.json
3.在项目本地安装webpack和webpack-cli
cnpm i webpack webpack-cli -D
注: -D是--save-dev的缩写
-S是--save的缩写
区别:-D是只在开发环境即dev中使用,项目发布以后就不会使用到,如babel,loader等
-S是在开发和正式环境都会用到,如jq,Vue等
4.打包第一个js文件
在根目录新建一个hello.js文件,然后执行
webpack hello.js hello.bundle.js
会得到一个警告一个错误

error1.png

这是因为webpack4与之前不太一样
webpack4.x的打包已经不能用
webpack 文件a 文件b
的方式,而是直接运行
webpack --mode development(开发环境)
或者
webpack --mode production(发布模式)
这是 webpack 4 引入的模式,包括 development、production、none 三个值,我们不传入值的话,默认使用 production进行打包。
我们可以在package.json,script字段中添加以下设置:
"dev":"webpack --mode development", "build":"webpack --mode production"
这样,我们就能直接使用命令 npm run dev 或 npm run build 来进行文件的打包处理。
webpack4.x会以项目根目录下'./src/index.js'作为入口,单单创建src文件夹或者没有index.js文件都会报错,输出路径是'./dist/main.js',dist目录及main.js会自动生成。
5.打包一个css文件
安装
css-loader:使webpack可以处理css文件
style-loader:新建一个style标签,把css-loader处理过的文件放进去,然后插入到HTML标签中
第一种方法:
在js文件中引入css文件,然后在文件名之前添加对应的loader
require('style-loader!css-loader!./style.css')
第二种方法:
在执行webpack命令时添加
webpack --mode development --module-bind "css=style-loader!css-loader"
其他的一些参数
--watch:监控文件变化,一旦文件有变化,就重新构建。但默认情况下,watch 选项是禁用的。
--progerss:会出现打包过程,有百分比进度条
--display-modules:会把所有打包的模块列出来
--display-reasons:会把打包的原因列出来
第三种方法:
添加webpack配置文件,稍后会写出。
6.添加配置文件
webpack4学习了parcel的0配置,所以也可以不需要配置文件
这里webpack的配置文件并没有太大变化

// 单入口文件
const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  }
}
// 多入口文件
const path = require('path')

module.exports = {
  entry: {
    main: './src/index.js',
    a: './src/a.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  }
}

注意:1.输出路径是path.resolve(__dirname, 'dist')
2.多文件的输出文件名不能固定
3.如果不写入口出口路径则使用webpack4默认的路径
7.添加加载loaders
1.预处理css,less
安装less,less-loader,css-loader,style-loader,postcss-loader和autoprefixer
cnpm install less less-loader css-loader style-loader postcss-loader autoprefixer -D
然后添加模块,规则

module: {
    rules: [
      {
        test: /\.less$/,
        loader: 'style-loader!css-loader!postcss-loader!less-loader'  // 从右到左执行,所以注意顺序  
      }
    ]
  }

为了加webkit等前缀需要在webpack.config同级下创建一个postcss.config.js文件导入autoprefixer自动补全

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}

还需在package.json文件中添加判断浏览器版本

"browserslist": [
    "> 1%",       // 全球浏览器使用率大于1%,最新两个版本并且是IE8以上的浏览器,加前缀  
    "last 2 versions",
    "not ie <= 8"
  ]

8.加入babel对es6语法进行转译
cnpm install babel-loader babel-core babel-preset-env --save-dev

{
        test: /\.js$/,               // 匹配js文件
        loader: 'babel-loader',
        exclude: path.resolve(__dirname, 'node_modules'),    //匹配时忽略这个目录,提高打包速度
        include: path.resolve(__dirname, 'src'),             // 匹配时查找的范围
        query: {
          presets: ['env']
        }
      }

9.开启实时更新
安装wbepack-dev-server
cnpm i webapck-dev-server -D
为了每次编译完成后删除上次打包的结果,添加删除插件clean-webpack-plugin,但是他也会删除我们的index.html,所以还需要安装自动生成html插件
cnpm i clean-webpack-plugin html-webpack-plugin -D

const Webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

// devServer和plugins是与module同级的
entry:,
output: ,
module: {
    rules: []
},
devServer: {
    // 设置服务器访问的基本目录
    contentBase: path.resolve(__dirname, 'dist'), //最好设置成绝对路径
    // 设置服务器的ip地址,可以是localhost
    host: 'localhost',
    // 设置端口
    port: 8090,
    // 设置自动打开浏览器
    open: true,
    // 设置自动更新
    hot: true
  },
  plugins: [
    new Webpack.HotModuleReplacementPlugin(),
    new CleanWebpackPlugin(['dist']), //传入数组,指定要删除的目录
    new HtmlWebpackPlugin({
      template: './index.html',               // 会与根目录下的index.html相关联,把根目录下index的东西都放到生成的HTML中
      filename: 'index.html',         // 生成的HTML名,路径为上面output中的path,不填默认是index.html
      title: '测试webpack',
      hash: true,
      chunks: ['main'],  // 多页面分别引入自己的js
      minify: {
        collapseWhitespace: true,  //折叠空白区域 也就是压缩代码
        removeComments: true, //移除HTML中的注释
      }
    })
  ]

注意:热更新只针对js文件和样式文件,html不能热更新
10.仔细讲下html-webpack-plugin
多页面时需要写多个new HtmlWebpackPlugin

    new HtmlWebpackPlugin({
      template: './index.html',               // 会与根目录下的index.html相关联,把根目录下index的东西都放到生成的HTML中
      filename: 'index.html',         // 生成的HTML名,路径为上面output中的path,不写默认为index.html
      title: '测试webpack',
      hash: true,
      //inject: 'body', //指定链接注入在<head>标签中还是<body>标签中,为false值时表示不自动注入文件中,需要手动设置
      chunks: ['main'],  // 多页面分别引入自己的js
      minify: {
        collapseWhitespace: true //折叠空白区域 也就是压缩代码
      }
    }),
    new HtmlWebpackPlugin({
      template: './index.html',               // 会与根目录下的index.html相关联,把根目录下index的东西都放到生成的HTML中
      filename: 'a.html',         // 生成的HTML名,路径为上面output中的path,不写默认为index.html
      title: '测试webpack',
      hash: true,
      //inject: 'body', //指定链接注入在<head>标签中还是<body>标签中,为false值时表示不自动注入文件中,需要手动设置
      chunks: ['main', 'a'],  // 多页面分别引入自己的js
      minify: {
        collapseWhitespace: true //折叠空白区域 也就是压缩代码
      }
    })

还可通过这种方式自己引入

<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
<script type="text/javascript" src="<%=htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %>

11.添加vue
安装vue
cnpm install vue -S
安装vue-loader
cnpm install vue-loader -D
创建一个.vue后缀的文件,然后修改main.js文件

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)

然后修改webpack.config文件,添加vue-loader
注意:vue-loader15.0版本之后需要独立引入VueLoaderPlugin

const VueLoaderPlugin = require('vue-loader/lib/plugin')
{
        test: /\.vue$/,
        loader: 'vue-loader'
}

如果你没有安装css预处理,或者在style部分没有添加lang=*,这时打包会报错

error.png

明显这是未对vue文件中的style部分正确的编译,所以安装vue-style-loader并添加loader

cnpm install vue-style-loader -D
{
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      },

注意:如果在main.js中的写法和vue-cli官方脚手架一样是这样的

new Vue({
  el: '#app',
  components: {App},
  template: '<App/>'
})

则运行dev会出现警告


warn.png

如果在代码中要使用到template编译模版(比如传入一个字符串给 template 选项,或挂载到一个元素上并以其 DOM 内部的 HTML 作为模板),则需要完整版的vue。
当使用 vue-loader 或 vueify 的时候,*.vue 文件内部的模板会在构建时预编译成 JavaScript。你在最终打好的包里实际上是不需要编译器的,所以只用运行时版本即可。
因为运行时版本相比完整版体积要小大约 30%,所以应该尽可能使用这个版本。如果你仍然希望使用完整版,则需要在webpack.config里配置一个别名:

module.exports = {
  // ...
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }
}

12.在vue文件里添加图片
在vue文件中添加图片,然后打包会报错

error.png

提示我们缺少file-loader,安装即可,且不用添加loader到webpack.config文件
cnpm i file-loader -D
打包时对图片的编译我们使用url-loader,他会将图片转为base64格式添加到网页中,url-loader也依赖于file-loader,所以也需要安装file-loader

cnpm i url-loader file-loader -D
{
        test: /\.(gif|jpg|jpeg|png|svg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 1024, //表示图片最大为1024KB 
              name: '[name].[ext]'  // 生成的文件名
            }
          }
        ]
      }

13.根据多环境选择不同的配置
安装cross-env
cnpm i cross-env -D
修改package.json文件

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --mode development",
    "build": "cross-env NODE_ENV=production webpack --mode production"
  },

这里的NODE_ENV会添加到process.env上,怎么添加呢?

const isDev = process.env.NODE_ENV === 'development'
const devAPI = '"http://localhost:8080"'
const proAPI = '"http://localhost:3000"'
// 注意一定是单引号加双引号的形式
...
plugins: {
...
new Webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: isDev ? '"development"' : '"production"',
        API_HOST: isDev ? devAPI : proAPI
      }
    })
...
}

另外可以将整个对象命名为config,然后根据isdev去给config添加配置,最后再将config暴露出去

const config = {......}
if(isDev){
  config.devtool = '#cheap-module-eval-source'
}
module.exports = config

14.将css单独打包
安装extract-text-webpack-plugin
注意:webpack4中需要使用的extract-text-webpack-plugin版本比较高,需要指定版本
查看包的所有版本
cnpm view extract-text-webpack-plugin versions
安装包的最新版本
cnpm i extract-text-webpack-plugin@next -D

const ExtractTextPlugin = require('extract-text-webpack-plugin')
...
{
        test: /\.less$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            'css-loader',
            {
              loader: 'postcss-loader',
              options: {
                sourceMap: true
              },
            },
            'less-loader'
          ]
        })
}
...
plugins:  {
    new ExtractTextPlugin({
        filename: 'css/app.[hash].css',
        chunkFilename: 'css/app.[contenthash].css'
}

webpack4中extract-text-webpack-plugin已经不再被推荐使用,推荐使用新的插件mini-css-extract-plugin
安装mini-css-extract-plugin
cnpm i mini-css-extract-plugin -D

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
...
{
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true
            },
          },
          'less-loader'
        ]
      },
...
new MiniCssExtractPlugin({
      filename: 'static/css/app.[hash].css',
      chunkFilename: 'static/css/app.[contenthash].css'
    })

15.将第三方库单独打包(不是很明白)
因为CommonsChunkPlugin被删除, 改为内置的api--optimization,同plugins同级

...
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          name: 'vendor',
          chunks: 'initial',
          minChunks: 2
        },

      }
    }
  },
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,192评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,186评论 1 303
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,844评论 0 252
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,471评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,876评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,891评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,068评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,791评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,539评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,772评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,250评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,577评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,244评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,146评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,949评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,995评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,812评论 2 276

推荐阅读更多精彩内容