前言

随着前端工程化,webpack已经是必不可少的打包工具,然鹅,我们在日常工作中,都是使用vue-cli等脚手架,0配置直接写业务代码,这个我个人是支持的,毕竟这样可以让同学萌更专注业务代码。

但是假如你想鹤立鸡群,让面试官眼前一亮,那么webpack的配置,确实需要了解一下。

太久没有从0配置webpack,也借这一篇文章,让自己温故知新吧~

假如本文有错误的地方,希望能指正?。

假如您是已经对webpack十分熟悉的,那么你可以右上角关掉...

环境
  • webpack 4.43.0版本

  • node v12.16.1版本

入门

注意了,我这里是使用cnpm的,你们喜欢用npmyarn都可以

  • cnpm i -Dcnpm install --save-dev的缩写,开发依赖

  • cnpm i -Scnpm install --save的缩写,运行依赖

简单解释一下什么是开发依赖运行依赖

  • 开发依赖devDependencies,就是开发时候的依赖,例如loaderplugin等等,不会被打包的,在线上不需要的

  • 运行依赖dependencies,就是运行时候的依赖,例如vueaxios等,是会被打包上线的

说了那么多,终于可以下载webpack了?

先下载全局webpack(不全局安装也行,这里不做讨论,毕竟才入门,越简单越好)

-gglobal的意思,全局安装

cnpm i -g webpack webpack-cli

新建一个项目目录,就叫demo吧,进入该项目后输入命令

npm init

这个时候,会有一堆东西让你填写,括号内是默认值,一路回车即可

package name: (webpack)version: (1.0.0)description:entry point: (index.js)test command:git repository:keywords:author:license: (ISC)Is this OK? (yes)

假如你连回车都不想多按,自动选中所有默认值,那么你可以这样做?

npm init -y

这个时候demo下有了一个package.json文件,里面有我们刚刚一路回车选中的东西,我们先不用管这个文件

其实这个时候已经可以使用webpack了,先感受一下真0配置

新建一个文件夹src,在src里面建一个index.js文件

console.log("前端背锅侠");

然后在终端中执行webpack指令

webpack

你会发现项目下多了两个文件夹distnode_modules,打开dist->main.js,你会看到有一大堆代码(多了一大坨代码是由于webpack做了模块化处理),并且最后有几个中文字前端背锅侠?

恭喜你,打包成功

基础配置

在根目录新建一个webpack.config.js,为啥叫这个名字呢?

打开webpack源码你会发现webpack-cli/bin/config/config-yargs.js里面的defaultDescription,你会有惊喜,这里不做深入研究

const { resolve } = require('path');module.exports = {mode: 'development', // 开发模式,有两种模式production【生产模式】和development【开发模式】    entry: resolve(__dirname, './src/index.js'), // 入口文件    output: {filename: 'index.js', // 打包后的文件名称        path: resolve(__dirname, './dist'), // 打包后的目录    },};

删掉dist文件,再执行webpack在打包一次,发现又成功了,这个时候你可以切换mode模式,感受一下生产模式开发模式

在这个配置上加上hash

const { resolve } = require('path');module.exports = {mode: 'development', // 开发模式,有两种模式production【生产模式】和development【开发模式】    entry: resolve(__dirname, './src/index.js'), // 入口文件    output: {filename: 'index[hash].js', // 打包后的文件名称        path: resolve(__dirname, './dist'), // 打包后的目录    },};

发现,文件名竟然改掉了,加了一大串hash,并且发现,只有我们在改了src/index.js的文件代码后,打包的文件名字才会发生改变。对的,这就是hash的作用,只有文件发生改变的时候,hash才会发生变化,这样就完美解决缓存问题了。

假如你不喜欢那么长的hash你也可以这样配置index[hash:5].js

现在是打包js,那么怎么看在页面上行不行呢?

webpack-dev-server 及 html-webpack-plugin

src目录下新建index.html文件,并且把基本东西填写好

cnpm i webpack-dev-server html-webpack-plugin -D

配置

// webpack.config.js

const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {mode: 'development', // 开发模式,有两种模式production【生产模式】和development【开发模式】    entry: resolve(__dirname, './src/index.js'), // 入口文件    output: {filename: 'index[hash:5].js', // 打包后的文件名称        path: resolve(__dirname, './dist'), // 打包后的目录    },devServer: {port: 3000, //  端口        progress: true, //  进度条        open: true, //  自动打开浏览器        compress: true, //  压缩    },plugins: [new HtmlWebpackPlugin({template: './src/index.html', //  模板目录            filename: 'index.html', //  打包后的文件            minify: {removeAttributeQuotes: true, //  删除双引号                collapseWhitespace: true, //  折叠空行            }        }),    ],};

这个时候我们需要在package.json里面增加一点指令,方便我们操作

{    ...    "scripts": {        "dev": "webpack-dev-server",        "build": "webpack"    },    ...}

先执行

npm run dev

webpack最不想看到的东西出现了...卧槽...报错了...???

但是不要慌,看看报错的内容...Error: Cannot find module 'webpack',找不到webpack

是的,还记得我们开始就是全局安装webpack,而不是当前项目安装吗?

我们尝试在这个项目安装一下

cnpm i webpack webpack-cli -D

此时再运行,能完美自动打开浏览器,并且在控制台中显示了前端背锅侠

并且我这个时候,修改index.html或者index.js,浏览器会自动显示我们想要的东西...妈耶..太爽了?

我们再执行另外的指令

npm run build

dist目录下的文件就是我们想要的东西!!!!?

那么,假如多页面多入口(一个HTML对应一个以上JS),咋搞?

同样html-webpack-plugin可以帮我们解决

我们先在src目录下新建test.htmltest.js,并且在里面随便写的东西

// webpack.config.js

const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {mode: 'development',//  注意    entry: {index: resolve(__dirname, './src/index.js'),test: resolve(__dirname, './src/test.js'),    },//  注意    output: {filename: '[name][hash:5].js',path: resolve(__dirname, './dist'),    },devServer: {port: 3000,progress: true,open: true,compress: true,    },//  注意    plugins: [new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',chunks: ['index'],        }),new HtmlWebpackPlugin({template: './src/test.html',filename: 'test.html',chunks: ['test'],        }),    ],};

为了更简洁更突出我修改的地方,我把一些注释及一些HtmlWebpackPluginminify删掉

三点需要注意的地方

  • entry入口改为key/value形式

  • output输出改为[name][hash:5].jsname就是你入口所命名的key

  • plugins插件中new了2个HtmlWebpackPlugin,并且chunks写入口所命名的key

这个时候再build,你会发现,多入口文件已经实现

留给同学萌一个小实验,假如一个HTML对应多个JS,咋搞?

提示HtmlWebpackPlugin里面的chunks是一个数组哦!!?

不知道你们会不会觉得,每次build之前都要手动删除dist,感觉好繁琐,有好的办法解决吗?

答案是肯定的

clean-webpack-plugin

下载clean-webpack-plugin

cnpm i clean-webpack-plugin -D
// webpack.config.js

const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = {mode: 'development',entry: resolve(__dirname, './src/index.js'),output: {filename: 'index[hash:5].js',path: resolve(__dirname, './dist'),    },devServer: {port: 3000,progress: true,open: true,compress: true,    },plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',minify: {removeAttributeQuotes: true,collapseWhitespace: true,            },        }),    ],};

其实就很简单,在pluginsnew CleanWebpackPlugin()即可

css

我们在src下新建一个index.css并且写入一些样式,并且在index.js中引入

import './index.css';console.log('前端背锅侠');

运行一下,npm run dev,你会发现样式无效,并且控制台报错

这个时候就需要loader来处理了

cnpm i style-loader css-loader -D
// webpack.config.js

const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = {mode: 'development',entry: resolve(__dirname, './src/index.js'),output: {filename: 'index[hash:5].js',path: resolve(__dirname, './dist'),    },devServer: {port: 3000,progress: true,open: true,compress: true,    },plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',minify: {removeAttributeQuotes: true,collapseWhitespace: true,            },        }),    ],module: {rules: [            {test: /\.css$/,use: ['style-loader', 'css-loader'], //  从左往右解析            },        ],    },};

我们重新再跑一遍npm run dev,你会发现,样式生效了,并且审查元素的时候,发现样式在head里面

当然,相信你们在工作中也不会纯写css,肯定是sassless或者stylus

我们用sass举例

sass-loader

下载

cnpm i sass-loader node-sass -D

我们直接把index.css改为index.scss,并且在index.js中修改引入的路径

//  webpack.config.js

//  由于代码太长,我就不重复复制了

module: {rules: [        {test: /\.css$/,use: ['style-loader', 'css-loader'],        },        {test: /\.(scss|sass)$/,use: ['style-loader', 'css-loader', 'sass-loader'],        },    ],}

重新npm run dev,效果也出来了

postcss-loader 及 autoprefixer

如果我说,有loader可以自动帮我们添加浏览器前缀,你会不会觉得样式兼容不再是个棘手的问题??

cnpm i postcss-loader autoprefixer -D
//  webpack.config.js

module: {rules: [        {test: /\.(scss|sass)$/,use: ['style-loader','css-loader',                {loader: 'postcss-loader',options: {plugins: [require('autoprefixer')],                    },                },'sass-loader',            ],        },    ],},
//  package.json{ ... "browserslist": ["last 2 versions", "> 1%"]}

这里有其他的配置方式,这里不深入讨论

重新npm run dev,看到css的样式全部都加了后缀,真香~

样式抽离 mini-css-extract-plugin

如果样式很多,全部写在head里面貌似也不是我们想要的,我们需要抽离

下载mini-css-extract-plugin

cnpm i mini-css-extract-plugin -D
//  webpack.config.js

//  代码太长,省略了部分代码const MiniCssExtractPlugin = require('mini-css-extract-plugin');module.exports = {plugins: [new MiniCssExtractPlugin({filename: 'css/[name][hash:5].css',        }),    ],module: {rules: [            {test: /\.(scss|sass)$/,use: [/**                     * 注意,这里本来应该是style-loader                     * 但是由于我们现在不需要将css写在head,而是抽离                     * 所以用MiniCssExtractPlugin.loader代替                     */                    MiniCssExtractPlugin.loader,'css-loader',                    {loader: 'postcss-loader',options: {plugins: [require('autoprefixer')],                        },                    },'sass-loader',                ],            },        ],    },};

引入图片

假如你没有相关配置,你是无法引入背景图片的,不信你试试??

body {background: url('images/img2.png');#test {display: flex;background: url('images/img.png');height: 100px;width: 100px;background-size: 100% 100%;    }}

下载url-loader

cnpm i url-loader file-loader -D
//  webpack.config.js

module: {rules: [        {test: /\.(jpe?g|png|gif)$/i,use: [                {loader: 'url-loader',options: {limit: 10 * 1024,outputPath: 'images',publicPath: "../images"                    },                },            ],        }    ],},

注意limit是限制大小,如果图片小于10k那么就将图片转为base64从而减少请求,达到优化,但是假如图片大于10k,那么转base64还不如直接请求

通过上面配置后,你会发现,正如我所说的...?

当你觉得一切万事大吉的时候,你在HTML上写上了这一句

<img src="./images/img2.png" alt="" />

又炸了...?

这个时候需要html-withimg-loader来处理

cnpm i html-withimg-loader -D
//  webpack.config.js

module: {rules: [        {test: /.html$/,use: 'html-withimg-loader',        }    ],},

当我愉快地以为这就可以的时候,我发现页面上一直404,经过多番查阅,才发现..原来有些file-loader改了配置!!?

//  webpack.config.js

module: {rules: [        {test: /.html$/,use: 'html-withimg-loader',        },        {test: /\.(jpe?g|png|gif)$/i,use: [                {loader: 'url-loader',options: {limit: 10 * 1024,//  要在这里加上这一句                        esModule: false,outputPath: 'images',publicPath: '../images',                    },                },            ],        },    ],},

JS转为兼容版本

我们先试试新语法打包出来的结果是咋样的

//  index.js

const name = '前端背锅侠'

我们执行打包npm run build,然后看dist目录下的index.js,在代码的最后部分发现了

eval("const name = '前端背锅侠'\n\n//# sourceURL=webpack:///./src/index.js?");

发现const并没有被转到低版本

这个时候babel出场了

cnpm i babel-loader @babel/core @babel/preset-env -D

我们重新build一遍,发现dist目录下的index.js,发生了改变

eval("var name = '前端背锅侠';\n\n//# sourceURL=webpack:///./src/index.js?");

const变成了var

但是不要高兴太早,当我们试试Promise语法的时候,你就发现,并没有达到预期的效果

这个时候我们还需要另外一个东西@babel/polyfill

cnpm i @babel/polyfill -D
//  webpack.config.js

//  入口文件修改entry: ['@babel/polyfill', resolve(__dirname, './src/index.js')],

我们试一下新的API,试试效果

// src/index.js

Promise.resolve('前端背锅侠').then(console.log);

这个时候,你再build一遍,你就发现,dist目录下的index.js,搜索一下前端背锅侠,你会发现,貌似没有编译到低版本的语法呀??

其实已经是低版本的语法了,你认真比一下有没有加@babel/polyfill打包出来的文件,大小都不一样。

你认真看打包后的文件,你会发现,原来babel把新API都用兼容语法重写了一遍!?

eslint

相信代码唐僧eslint肯定在日常开发中,能帮你们团队解决了很多规范问题

cnpm i eslint eslint-loader -D
module: {rules: [        {test: /\.js$/,use: {loader: 'eslint-loader',options: {enforce: 'pre', // enforce强制的意思 pre(前面执行) post(后面执行)                },            },        },    ],},

在根目录创建.eslintrc.js

module.exports = {env: {browser: true,es6: true,node: true,    },parserOptions: {sourceType: 'module',    },rules: {quotes: ['error', 'single'],    },};

更多的eslint规则,建议到eslint官网,自己配置,这里我就只写一个单引号的规则

修改src下的index.js

美丽的红色波浪线又出现了,唐僧啊~~?

如果你能看到这里,并且能跟着敲,那么你已经离成功就差一步了,加油,别放弃啊,骚年?

【基本配置】到此结束,接下来进入配置vue的章节


配置vue

下载vue相关的东西

cnpm i vue-loader vue-template-compiler vue-style-loader -Dcnpm i vue -S

我们就在上面的基础上继续搭建vue

先将src下面的东西清空,然后新建以下文件

// src/index.js

import Vue from 'vue';import App from './App.vue';new Vue({el: '#app',render: (c) => c(App),});


<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Documenttitle>head><body><div id="app">div>body>html>
//  src/App.vue

{{ msg }}

回到webpack.config.js

const { resolve } = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');const MiniCssExtractPlugin = require('mini-css-extract-plugin');const VueLoaderPlugin = require('vue-loader/lib/plugin');module.exports = {mode: 'development',entry: ['@babel/polyfill', resolve(__dirname, './src/index.js')],output: {filename: 'index[hash:5].js',path: resolve(__dirname, './dist'),    },devServer: {port: 3000,progress: true,open: true,compress: true,    },plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './src/index.html',filename: 'index.html',minify: {removeAttributeQuotes: true,collapseWhitespace: true,            },        }),new MiniCssExtractPlugin({filename: 'css/[name][hash:5].css',        }),new VueLoaderPlugin(),    ],module: {rules: [            {test: /\.vue$/,use: ['vue-loader'],            },            {test: /\.js$/,use: {loader: 'babel-loader',options: {presets: ['@babel/preset-env'],                    },                },exclude: /node_modules/,            },            {test: /\.(jpe?g|png|gif)$/i,use: [                    {loader: 'url-loader',options: {limit: 10 * 1024,esModule: false,outputPath: 'images',publicPath: '../images',                        },                    },                ],            },            {test: /\.(scss|sass)$/,use: [                    MiniCssExtractPlugin.loader,'css-loader',                    {loader: 'postcss-loader',options: {plugins: [require('autoprefixer')],                        },                    },'sass-loader',                ],            },        ],    },};

虽然扔了一大坨代码上来,但是细心的你,肯定发现,其实就只是加了一个loaderplugins罢了

跑起来看看效果吧...

成功了...?

好的..本文就到这里结束了...写那么长的文章...真的累~

假如你webpack真的不熟悉,个人建议你还是多敲几遍,自然你就熟悉了

其实还有很多配置没有说,例如:环境区分,别名配置、打包优化等等等,个人建议你还是多翻阅更多的资料,到webapck的官网上面认真细读一下,不要做一个伸手党...

工作中,假如没有那么多时间配置webpack,还是老老实实用脚手架吧?

本文属个人理解,如有错误,期待你的提出及交流,谢谢。

扫码进入前端交流群

扫码进入前端交流群

cnpm安装webpack_【6000字】从0到1,配置webpack相关推荐

  1. cnpm安装webpack_快速打造最强 Webpack 前端工具链

    当前,前端技术日新月异,公司的团队技术栈和业务场景不同,都会建立自己的前端工程体系.一个好的工程体系能够保证团队的研发流程规范,提高团队的研发效率,能够减少人员流动带来的项目交接和维护成本.2-3个项 ...

  2. cnpm安装失败及解决方案

    1.首先要去配置node.js,直接去node.js官网(http://nodejs.cn/) 下载node-vx.x.x.pkg文件双击一路默认安装即可,安装完在终端输入: node -v 如果显示 ...

  3. java实训感想6000字_JAVA论文6000字:无线校园

    论文最好能建立在平日比较注意探索的问题的基础上,写论文主要是反映学生对问题的思考, 详细内容请看下文JAVA论文6000字. 随着网络应用日益丰富,传统局域网络已经不能满足师生对移动网络的要求,无线局 ...

  4. Oracle Linux 6.9安装和Oracle 11.2.0.4.0安装及psu补丁升级

    原文有图图https://www.linuxidc.com/linux/2018-09/154218.htm 图文详解在Oracle Linux 6.9安装和Oracle 11.2.0.4.0安装及p ...

  5. 无法安装或运行此应用程序。该应用程序要求首先在“全局程序集缓存(GAC)”中安装程序集stdole版本7.0.3300.0...

    无法安装或运行此应用程序.该应用程序要求首先在"全局程序集缓存(GAC)"中安装程序集stdole版本7.0.3300.0 2011年12月21日 windows系统中目录 win ...

  6. 使用cnpm安装 React

    React 17.0.1 安装 使用cnpm安装react $ cnpm install -g create-react-app$ create-react-app react-learning$ c ...

  7. 前端开发之cnpm安装总是失败--已解决

    租了一台新电脑,之前电脑开发实在是太卡了,对于做前端开发的小伙伴nodejs,cnpm啥的肯定是必装.其他还好,安装完nodejs后执行node -v +npm -v都是正常的,接下来就该安装cnpm ...

  8. tensor搭建--windows 10 64bit下安装Tensorflow+Keras+VS2015+CUDA8.0 GPU加速

    windows 10 64bit下安装Tensorflow+Keras+VS2015+CUDA8.0 GPU加速 原文见于:http://www.jianshu.com/p/c245d46d43f0 ...

  9. Ubuntu14.04 64位机上安装OpenCV2.4.13(CUDA8.0)版操作步骤

    Ubuntu14.04 64位机上安装CUDA8.0的操作步骤可以参考http://blog.csdn.net/fengbingchun/article/details/53840684,这里是在已经 ...

最新文章

  1. 【微读书】《人工智能颠覆未来战争》连载之一:机器战胜人类?——AlphaGo人机对战的启示...
  2. 2021年信号与系统处理期中考试与课堂交互分数
  3. 2020-11-05 关于前端‘古董‘dojo的树结构如何默认展开根节点
  4. [原] 探索 EventEmitter 在 Node.js 中的实现
  5. Callable和Future接口的实现
  6. Swoole的think-swoole的安装
  7. python语言变量随时声明_2. Go语言五种变量创建的方法
  8. HTTPS协议详解:TLS/SSL握手过程
  9. 访问受限 诺基亚禁止Navifirm获取固件(图)
  10. Python中用冒号表达式对列表切片
  11. SM4算法 C语言 (从OpenSSL库中分离算法:七)
  12. AD9361射频捷变收发器系列对比
  13. 【PS | 学习】毛坯乡间图打造复古美式电影海报图
  14. 前端必知必会的技术体系,再也不担心前端内卷了
  15. 小学语文思维导图免费模板合集!家长必收藏
  16. BZOJ 2339 【HNOI2011】 卡农
  17. [原创]网站文章页面添加分享按钮,百度按钮代码复制使用时不显示问题解决!
  18. 概述纵横制电话交换机
  19. 全球与中国汽车空气悬架系统市场现状及未来发展趋势
  20. 信噪比SNR、符号信噪比Es/N0与比特信噪比Eb/N0的关系

热门文章

  1. 解决QT编程出现 C2001错误
  2. ASP.NET的几个试题(《C#与.NET程序员面试宝典》)
  3. Java中的静态方法和单例模式比较
  4. 找不到可安装的ISAM
  5. mysql 从中英文混合串中截取字符
  6. PowerDesigner模型设计1
  7. makefile模板
  8. Linux符号连接的层数过多
  9. Go搭建REPL环境
  10. OpenGL环境搭建(四)