https://juejin.im/post/5e5a8cac6fb9a07cd942b396css
随着前端工程化的愈来愈疯狂,不会点webpack的前端真的吃不香,睡不着。html
今天.我决定手把手带你入门webpack前端
所谓webpack就是一个现代 JavaScript 应用程序的静态模块打包器。vue
开胃菜
吃饭前先来一道开胃菜,看完这遍文章你会学到什么?node
- 了解什么是webpack
- 知道怎么去打包静态资源
- 知道几个(entrt,output,module,plugins等)核心的配置做用
- 不用vue-cli,从0到1跑起本身的vue项目
- 不用create-react-app,从0到1跑起本身的react项目
- 搭建一个既能跑vue项目也能跑react项目的配置
以上这些都是你将会学到的。react
舒适提示:建议跟着一块儿敲,这会加深你对每个知识的理解和固定; 还有内容有点多,须要你静下心来慢慢的品尝,你会收获到你意想不到的知识。webpack
入门webpack
1.1初始化项目
先咱们先在本身舒服的地方建立一个文件夹,文件夹里面初始化项目。es6
mkdir myWebpackPro
npm init -y
复制代码
而后咱们安装webpack webpack-cli 到项目web
npm i webpack webpack-cli -D
复制代码
你也能够用cnpm 或者yarn 来安装vue-cli
cnpm i webpack webpack-cli -D / yarn add webpack webpack-cli -D
复制代码
接着咱们在myWebpack文件夹建立一个src文件夹,在里面建立一个index.js文件(这个未来将是咱们的入口文件)。
mkdir src cd src touch index.js 复制代码
最后咱们在与src同级建立一个webpack.config.js(配置webpack的文件)文件
touch webpack.config.js
复制代码
最终的目录结构是这样的

到此为止,咱们初始化项目就完成了。
1.2测试webpack可否正常打包
首先,咱们在index.js里面随便**console.log()**一句

而后到package.json的script下配置一下build命令,先删除默认的test命令,再添加build命令:
"build":"webpack ./src/index.js" 复制代码

最后咱们再终端执行npm run build命令
npm run build
复制代码
若是执行成功的话在根目录会多一个dist文件夹里面会有一个main.js

让咱们打开main.js看看有没有把咱们刚刚console.log()的那句话打包进去。

如今让咱们真正进入webpack配置。
1.3更改webpack的入口和默认打包的文件名
首先,咱们打开webpack.config.js配置一下entry和output

咱们在顶层引进path模块,这是node内置的一个模块,无需单独安装,是用来出来文件路径的一个模块。咱们的打包入口(entry)依旧是刚刚建立的那个index.js文件,出口(output)也就是打包成功后,输出的位置(path)和文件名(filename),咱们输出的位置依旧选择了dist文件下,可是输出的文件名,咱们该为了index.js(以后咱们会将文件名改成动态的)
配置完这些后,咱们到package.json改一下打包路径,将以前的./src/index.js改成./webpack.config.js

咱们npm run build以后依旧能打包成功。

输出的文件名也变成了index.js,如今你会看到dist目录下还有个main.js,是否是感到很奇怪?不用奇怪,这是咱们上一次打包余留下来的,等下咱们未来说如何解决上一次打包余留下来的文件。
1.4新建一个index.html模版
首先,咱们在src下新建一个跑public文件夹,而后在里面新建一个index.html模版(用于咱们查看打包的js文件,以后再用于咱们vue或者react项目的惟一html渲染模版)
cd src mkdir public touch index.html 复制代码
新建完以后咱们将刚才打包好的js引进去看看,浏览器有没有打印出咱们console.log()。

可是,当咱们将output的filename改为动态以后,每次打包输出的文件名都不同,那么咱们每一次打包都要从新引用一次,这样特别麻烦。
1.5html-webpack-plugin
为了解决上面说的那个问题,咱们须要安装一下html-webpack-plugin插件。
npm run html-webpack-plugin -D
复制代码
安装完以后咱们在webpack.config.js配置一下plugins。

这里咱们配置了html-webpack-plugin,也把输入文件名改成了动态的了([name].[hash:8].js)。
咱们再npm run build,而后你会看到再dist下多一个index.html。接着打开它,发现控制台输出的跟咱们console.log()的值一致就对了。(记得在打包前,把以前在index.html手机引进的script标签去掉,不如打包会在控制台会报一个找不到文件名的错)
接下来,咱们来解决,打包后自动清除以前打包的代码。
1.6 clean-webpack-plugin
如今你打开dist好不少冗余的js文件,每次手动清除的话会很是烦躁。那咱们就让webpack来帮咱们作。

首先,安装clean-webpack-plugin。
npm i clean-webpack-plugin -D
复制代码
安装完以后,咱们再配置一下plugins选项。

注意⚠️:CleanWebpackPlugin是具名导出。
最后,咱们在npm run build一下,看看dist目录下还有没有多余的js文件。

soga,干净。
那么,如今问题又来,咱们每次改动一点js代码都要从新手动去打包一次,这样真炒鸡麻烦啊,那有没有自动打包的方法呢?那么答案来咯,固然是有的。下面咱们解决这个问题。
1.7 热更新
如今咱们来解决自动打包的问题。首先,咱们安装一下webpack-dec-server,配合webpack内置的HotModuleReplacementPlugin插件来完成热更新。
npm i webpack-dev-server -D
复制代码
HotModuleReplacementPlugin不用手动下载,webpack内置。
安装完以后,咱们先来配置一下webpack.config.js文件

配置完webpack.config.js,咱们的package.json添加一条打包命令

配置完后,咱们如今用npm run dev命令打包,而后咱们回去更新咱们index.js文件的任何东西,保存以后都会自动更新。
好了,如今基础功能,咱们搭建得差很少了。接下咱们配置module,继续完善最后的基础功能,好比打包js,css,image。
1.8 打包js文件
打包js文件,主要是要将es6,7...的语法转义成es5的语法,让不兼容es6,7...语法的浏览器也能使用。
首先咱们先安装一套包babel-loader,@babel/core,@babel/preset-env,@babel/polyfill。
npm i babel-loader @babel/core @babel/preset-env @babel/polyfill -D
复制代码
安装完以后,咱们来配置webpack.config.js的module。

这里简单介绍一下,每一个loader的做用,babel-laoder主要是打包js文件,而babel-loader又依赖@babel/core,@babel/preset-env能够转义es6的map,every,fifler,some...语法,可是不转义Promise,async,await...语法,因此要用@babel/polyfill来转义。
1.9 打包css文件
首先安装几个loader,style-loader,css-loader。
npm i style-laoder css-loader -D
复制代码
安装完,咱们接着配置module

这里只是简单配置css文件,可能有些项目还会用到less,scss等,这里就不过多阐述,若是你项目用到能够到官方找一下对应的loader配置一下,都是大同小异。
2.0 打包image,font,media文件
首先仍是先安装几个loader,url-laoder,file-loader。
npm i url-loader file-loader -D
复制代码
安装完,咱们继续配置module

介绍一下这两个loader的配置,配置里咱们指定了limit,若是文件没有大于这个就用url-loader,base64打包,若是大过这个值,就会用file-loader打包,同时会按options下配置的name输出到对应的位置。
好,基础配置就说那么多了,若是你的项目还有其余的需求能够到官网撸一番。
最终配置以下:
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const { CleanWebpackPlugin } = require('clean-webpack-plugin') const webpack = require('webpack') const config = { entry: ['@babel/polyfill', path.resolve(__dirname, './src/index.js')], output: { filename: '[name].[hash:8].js', path: path.resolve(__dirname, './dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_module/, use: [ { loader: "babel-loader", options: { presets: ['@babel/preset-env'] } } ] }, { test: /\.css$/, use: ['style-loader', 'css-loader'] }, { test: /\.(jpg|png|gif)$/, use: [ { loader: 'url-loader', options: { limit: 1024, fallback: { loader: 'file-loader', options: { name: 'img/[name].[hash:8].[ext]' } } } } ] }, { test: /\.(mp4|webm|ogg|mp3|wav)(\?.*)?$/, use: [ { loader: 'url-loader', options: { limit: 1024, fallback: { loader: 'file-loader', options: { name: 'media/[name].[hash:8].[ext]' } } } } ] }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: [ { loader: 'url-loader', options: { limit: 1024, fallback: { loader: 'file-loader', options: { name: 'fonts/[name].[hash:8].[ext]' } } } } ] } ] }, devServer: { port: '3000', host: '127.0.0.1', hot: true, open: true }, plugins: [ new HtmlWebpackPlugin({ filename: "index.html", template: path.resolve(__dirname, './src/public/index.html') }), new CleanWebpackPlugin(), new webpack.HotModuleReplacementPlugin() ] } module.exports = config 复制代码
从0到1跑起Vue项目
当你以上的基础部分都熟悉了,咱们从0到1搭建一个vue环境是soeasy的事。明人不说暗话,其实上面的基础部分一直在为跑起vue项目作铺垫。
如今咱们要跑起vue项目,在以上基础的配置上,在搞几个loader就完事了,简单得我都很差意思往下说了。
好了,如今咱们先来安装几个东西,vue,vue-loader,vue-template-compiler,vuw-style-loader
npm i vue vue-laoder vue-template-compiler vue-style-loader -D
复制代码
安装完以后,咱们来配置一下weback.config.js
这是module配置,记得在顶层导入VueLoaderPlugin

这是plugins配置

配置完webpack.config.js以后,咱们来在src下建立一个vue文件夹,而后在里面建立一个app.vue文件
cd src mkdir vue cd vue touch App.vue 复制代码
目录

接着在app.vue中,学上你熟悉的vue语法。

写好以后,咱们回到入口文件也是src下的index,js,咱们来从新写一下里面的逻辑,以前只是console.log()一下,什么也没作。
最后咱们的index.js文件是这样的。

这段代码对于用vue的同窗再也熟悉不过来。
接着,咱们回到src下的public下的index.html加一个根元素加上一个id为root。

最后,咱们npm run dev一下,咱们的vue项目就跑起来了。
从0到1跑起React项目
咱们搭建React项目的配置,仍是重基础配置上面配置。跑起react项目的配置比vue还要简单。
首先,咱们先安装一些东西。react,react-dom,@babel/preset-react
npm i react react-dom @babel/preset-react -D
复制代码
安装完后,咱们配置一下webpack.config.js
它只须要配置一下module下的js项就ok了。

接着,咱们去写一下入口文件(index.js)的逻辑。

这段代码对用react的同窗也是熟悉不过的了。
index.html文件也根vue写的同样。

最后,咱们npm run dev一下,咱们的react项目的跑起来了。
到这里,咱们本身搭建Vue项目环境配置和React项目环境配置都说完了。
那么咱们怎么能够把Vue环境跟React环境统一在放下同一个环境下,在咱们学Vue的时候用Vue环境,在咱们写React的时候用React环境,这是咱们接下要作的。
一套配置,两套环境,既可跑Vue,也可跑React
咱们回头观察一下Vue的配置跟React的配置有哪里不一致,哪里是一致的。
同:
entry,output

image,font,media打包

devServer和部分Plugin

- js的loader配置,vue没有@babel/preset-ract
- css的loader的配置,vue用的是vue-style-loader,react用的是style-loader
- vue的loader,react配置没有
- plugin,vue多了一个VueLoaderPlugin,react没有
好了,如今咱们找出它们的异同之处了,那就好办了。
咱们须要用一个叫webapck-merge的插件,咱们安装一下。
npm i webpack-merge -D
复制代码
安装完以后,咱们在webapck.config.js同级目录下新建两个文件webpack.vue.js,webpack.react.js,来放它们二者不一样的配置。
touch webpack.vue.js
touch webpack.react.js
复制代码
接着咱们来写一下它们的不一样配置。
webpack.vue.js
const merge = require('webpack-merge') const webpackConfig = require('./webpack.config') const VueLoaderPlugin = require('vue-loader/lib/plugin') const config = { module:{ rules:[ { test:/\.vue$/, use:['vue-loader'] }, { test: /\.js$/, exclude: /node_module/, use: [ { loader: "babel-loader", options: { presets: ['@babel/preset-env'] } } ] }, { test: /\.css$/, use: ['vue-style-loader', 'css-loader'] }, ] }, plugins:[ new VueLoaderPlugin() ] } module.exports = merge(webpackConfig,config) 复制代码
webpack.react.js
const merge = require('webpack-merge') const webpackConfig = require('./webpack.config') const config = { module:{ rules:[ { test: /\.js$/, exclude: /node_module/, use: [ { loader: "babel-loader", options: { presets: ['@babel/preset-react','@babel/preset-env'] } } ] }, { test: /\.css$/, use: ['style-loader', 'css-loader'] }, ] } } module.exports = merge(webpackConfig,config) 复制代码
最后webpack.config.js就成这样了。
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const { CleanWebpackPlugin } = require('clean-webpack-plugin') const webpack = require('webpack') const config = { entry: ['@babel/polyfill', path.resolve(__dirname, './src/index.js')], output: { filename: '[name].[hash:8].js', path: path.resolve(__dirname, './dist') }, module: { rules: [ { test: /\.(jpg|png|gif)$/, use: [ { loader: 'url-loader', options: { limit: 1024, fallback: { loader: 'file-loader', options: { name: 'img/[name].[hash:8].[ext]' } } } } ] }, { test: /\.(mp4|webm|ogg|mp3|wav)(\?.*)?$/, use: [ { loader: 'url-loader', options: { limit: 1024, fallback: { loader: 'file-loader', options: { name: 'media/[name].[hash:8].[ext]' } } } } ] }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: [ { loader: 'url-loader', options: { limit: 1024, fallback: { loader: 'file-loader', options: { name: 'fonts/[name].[hash:8].[ext]' } } } } ] } ] }, devServer: { port: '3000', host: '127.0.0.1', hot: true, open: true }, plugins: [ new HtmlWebpackPlugin({ filename: "index.html", template: path.resolve(__dirname, './src/public/index.html') }), new CleanWebpackPlugin(), new webpack.HotModuleReplacementPlugin(), ] } module.exports = config 复制代码
好了,如今咱们把它们的配置拆分完毕了,还剩最后一步咱们就大功告成了,那就是在package.json添加两条命令。

在咱们写vue项目的时候,咱们就用npm run vue,在写react项目的时候,咱们就用npm run react。
结尾
好了,到如今为止,咱们把从基础配置到vue到react再到合并两套环境都作完了。原创不易,但愿这篇文章能帮助到你。若是有不到位,欢迎在下面留言;若是把你看得睡着过去的,欢迎来找我,我给你暖被窝,哈哈哈;若是有把你说蒙的了或者还不明白的,欢迎来找我,我把个人剩余的两个口罩送一半给你。
最后,我还想问各位大佬一下这句话什么意思,一个朋友发给个人:"油城壮志忆往昔,秋风吹叶道难行。莫问前路多迷茫,龙门跃起终识君"。我百度了也没有这首诗啊🤣。
