webpack

webpack是一个现代JavasScript应用程序的模块打包器(module bunder)

官方网站https://www.webpackjs.com/

安装方式

  • 全局安装

这里我使用npm

npm install webpack@版本号 webpack cli@版本号

如何查看其版本号

npm info webpack version

如何查看它所有的版本

npm info webpack
  • 本地安装

这里我使用yarn

yarn add webpack webpack-cli --dev

用途

  1. 转译代码(如:ES6转译成ES5,SCSS转译成CSS)
  2. 构建build
  3. 代码压缩
  4. 代码分析

如何运行webpack

这里我就以本地安装为例,要调用webpack:

./node_modules/.bin/webpack --version

上面这种方式看起来不是很方便,但是没有办法;因为本地安装后 。webpack node_modules中的bin 目录里面。但我们真的就只有这一种运行方式吗?作为一个程序员肯定不会使用这么麻烦的方式的。于是,便有了下面这种运行方式:

npx webpack

npx它可以自动在本地寻找webpack,就不需要向第一种方式去死记路径。


懂得了webpack的安装方式、运行方式;下面我们一起来看看它的用途具体是怎么操作的。

webpack转译JS

接刚刚我们运行了webpack,它会自动生成一个index.js;这个index.js就是转译后的js文件。与此同时它会有一个警告。

那这个警告怎么消除呢?下面我们就来说说这个警告到底怎么干掉它。

我们先读它的报错。它说我的mode没有设置,好就这一句我就知道问题的所在;接下来我们来配置一下:

makdir webpack.config.js
cd webpack.config.js
var path = require('path');

module.exports = {
  mode: 'development',
};

注意:这里需要说一下mode接受两个参

  1. development 开发情况下使用
  2. pruduction 给用户展示或是正要发布时使用

webpack配置entry和output

entry后接许转译的文件路径。(在这里也就是我们需要转译的文件,通常我们写在src中)

output转译后输出的结果放在output里;它含有path和filename。

const path = require('path')
 module.exports = {
    mode: 'development',
    entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
   }

注:path表示转译成功后的文件存放路径。

如:

path:path.resolve(dirname,'dist')//默认放在dist目录里

filename转译成功后的文件的名字属性。

如:

filename:‘main.js’//转译成功后的文件默认是main.js,但是这个文件名是可以手动修改的

为了方便浏览器快速加载,我们这里引入哈希:

filename:‘[name].[contenthash].js’

此方法优点在于方便js,css文件里面的内容修改后,自动更新其转译后的文件名方便浏览器快速更新请求;当然有优点就有缺点,它的缺点就是每一次更新转译后,dist目录就会新增一个更新的文件;所以我们需要更新前需要先删除过时的转译文件。(如:css、JS等)但是这对于一个程序员来说不利于快速开发,所以我们继续想办法优化这一缺陷;于是我们找到package.json文件,去配置它里面的scripts.build。

“build”:"rm -rf dist && webpack//先删除过时的转译文件,再重新转译更新后的文件

配置完build后,下一次我们更新完文件转译时就不用再使用npx webpack,直接使用yarn build。

webpack生成HTML

友情提示:在生成HTML之前建议大家先提交一下自己的代码,以防被自己给玩坏。

下面我们用webpack生成HTML,具体操作步骤如下:

yarn add html-webpack-plugin --dev //安装插件

在webpack.config.js中引入这个插件

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin')
module.exports = {
  mode: 'development',
  entry: {
      app: './src/index.js',
    },
  output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
}

引入完成后,在modlue.exports对象中添加plugin

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin')
module.exports = {
  mode: 'development',
  entry: {
      app: './src/index.js',
    },
  output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
  plugin:[new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)]
};

运行yarn build,html就以生成成功(运行yarn build后自动生成在dist目录下);如果我们想通过plugin中的title来设置html的title,那么就在assets中的index.html下的title标签里加上<%=htmlwebpackplugin.options.title%>。即:

<title><%=htmlwebpackplugin.options.title%></title>//自动引用plugin里面设置的title内容

友情提示:记得修改meta viewport。

webpack引入CSS

和MVC一样,这里通过模块化的方式。先在src下创建好x.css文件,然后在JS中通过import './x.css'引入。在运行yarn build之前我们需要安装两个插件:

yarn add css-loader --dev
yarn add style-loader --dev

安装成功后,我们在webpack.config.js中进行配置:

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin')
module.exports = {
  mode: 'development',
  entry: {
      app: './src/index.js',
    },
  output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
  plugin:[new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)],
module: {
 rules: [
      {
        test: /\.css$/,//这里使用到正则表达式。表示以.css文件结尾的
        use: ['style-loader', 'css-loader']//把以.css结尾的文件,先通过css-loader转换成JS代码,再通过style-loader将JS代码转成style标签,并将其内容写入到style标签内。最后插入到head标签上
};
]},

}

运行 yarn build

目前我们有了html,同时也引进了css,那么接下来我们怎么预览我们的html呢?

  • 方法一
http-server -c-1

通过此方式预览,我们可以看到基本正常;但是当我们打开控制台后发现我们的style标签怎么在head标签中显示出来呢?这个无非就给我们刚刚在webpack.config.js中的配置有关联;但是此预览方式对于我们来说是很繁琐的,每一次修改我们要回到上一层,修改后build完之后又要进入dist 目录进行预览。这样来回操作起来实在太繁琐,接下来我们来解决一下这个预览繁琐的问题。

  • 方法二

webpack-dev-sever

先安装插件

yarn add webpack-dev-server --dev

在webpack.config.js中配置

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin')
module.exports = {
  mode: 'development',
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
   devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)],
module: {
rules: [
      {
        test: /\.css$/,//这里使用到正则表达式。表示以.css文件结尾的
        use: ['style-loader', 'css-loader']//把以.css结尾的文件,先通过css-loader转换成JS代码,再通过style-loader将JS代码转成style标签,并将其内容写入到style标签内。最后插入到head标签上
};
]},

}

再到package.json中配置

"start": "webpack-dev-server --open",//加在scripts中

配置完成现在我们就可以通过使用yarn start来进行预览。通过start预览的好处在于我们修改完代码后是实时更新的,并不需要重新去build和去删除dist目录下的过期转译文件,而且它也不会生成dist目录,直接在内存中就搞定。

把CSS抽成文件

安装插件

yarn add mini-css-extract-plugin--dev

在webpack.config.js中配置

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  mode: 'development',
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
   devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[
new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
),
 new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
      ignoreOrder: false, 
    }),
],
module: {
rules: [
      {
        test: /\.css$/,//这里使用到正则表达式。表示以.css文件结尾的
         use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../',
              hmr: process.env.NODE_ENV === 'development',
            },
          },
          'css-loader',
        ],
       //注释下面的use
        use: ['style-loader', 'css-loader']//把以.css结尾的文件,先通过css-loader转换成JS代码,再通过style-loader将JS代码转成style标签,并将其内容写入到style标签内。最后插入到head标签上
};
]},

}

运行build。现在我们去dist目录,增加了一个main.css文件;打开index.html文件查看。此时html自动引入css文件:

<link href ="main.css",rel = "stylesheet">//插入到head标签中

目前css是抽成文件,但是我们无法在更新它;所以我们在进一步优化:

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  mode: 'development',
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
   devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[
new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
),
 new MiniCssExtractPlugin({
      filename: 'main.[contenthash].css',
      chunkFilename: '[id].[contenthash].css',
      ignoreOrder: false, 
    }),
],
module: {
rules: [
      {
        test: /\.css$/,//这里使用到正则表达式。表示以.css文件结尾的
         use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../',
              hmr: process.env.NODE_ENV === 'development',
            },
          },
          'css-loader',
        ],
       //注释下面的use
        use: ['style-loader', 'css-loader']//把以.css结尾的文件,先通过css-loader转换成JS代码,再通过style-loader将JS代码转成style标签,并将其内容写入到style标签内。最后插入到head标签上
};
]},

}

添加了[contenthash]

运行build

我知道肯定有人问不是应该用yarn start吗?

记住:修改代码用build,预览用start。

目前我们有两个命令,是否可以考虑使用两个webpack.config.js呢?先试试看看

copy一份webpack.config.js,重新命名webpack.config.prod.js;但是目前两个文件里的内容基本相同,所以这里我们就使用一下继承,把相同的属性放在同一个文件里;新建一个webpack.config.base.js。把相同的代码放在base文件里。

webpack.config.base.js文件

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
 devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[
new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)],
module: {
rules: [
      {
        test: /\.css$/,//这里使用到正则表达式。表示以.css文件结尾的
},

]},
}

webpack.config.js

const Htmlwebpackplugin = require('html-webpack-plugin')
const base = require('./webpack.config.base.js')
module.exports = {
...base,
  mode: 'development',
)],
module: {
rules: [
...base.modlue.rules,
      {
        test: /\.css$/,//这里使用到正则表达式。表示以.css文件结尾的
        use: ['style-loader', 'css-loader']//把以.css结尾的文件,先通过css-loader转换成JS代码,再通过style-loader将JS代码转成style标签,并将其内容写入到style标签内。最后插入到head标签上
};
]},
}

webpack.config.prod.js

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
...base,
  mode: 'production',
  plugin:[
...base.plugin,
 new MiniCssExtractPlugin({
      filename: 'main.[contenthash].css',
      chunkFilename: '[id].[contenthash].css',
      ignoreOrder: false, 
    }),
],
module: {
rules: [
...base.rules,
      {
        test: /\.css$/,//这里使用到正则表达式。表示以.css文件结尾的
         use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '../',
              hmr: process.env.NODE_ENV === 'development',
            },
          },
          'css-loader',
        ],
};
]},

}

我们现在将每一个命令设置指定文件

yarn start 默认指向webpack.config.js

yarn build通过--config指定,打开pakeage.json设置

"build": "rm -rf dist && webpack --config webpack.config.prod.js

经典面试题

  • loader与plugin的区别

loader是用来加载一个文件。如;加载JS文件,把JS文件转译成低版本浏览器可支持的JS;它也可以用来加载css文件,把css变成页面上的style标签和其他处理;也可以用来加载图片文件,把图片进行优化。

plugin是用来加强webpack功能的。如:有一个插件叫Htmlwebpackplugin它可以生成一个html文件;又如:minicssextractplugin,它是用来抽取css代码并把它变成一个文件。

webpack引入SCSS

安装插件

yarn add sass-loader dart-sass --dev

在webpack.config.base.js中配置

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
 devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[
new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)],
module: {
rules: [
      {
        test: /\.scss$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader','scss-loader']
},

]},
}

运行yarn build,会报错说找不到node-sass,所以,我们上面的设置是有误的,再次修改:

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
 devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[
new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)],
module: {
rules: [
      {
        test: /\.scss$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader',{
       loader:"sass-loader",
       options:{implementation:require('start-sass')}
}]
},

]},
}

运行 yarn build

webpack引入LESS和stylus

  • LESS-loader

安装插件

yarn add less-loader --dev

在webpack.config.base.js中配置

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
 devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[
new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)],
module: {
rules: [
      {
        test: /\.scss$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader',{
       loader:"sass-loader",
       options:{implementation:require('start-sass')}
}]
},
{
        test: /\.less$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader','less-loader']
}

]},
}

运行 yarn build,会报错找不到less,那就在装一个

yarn add less --dev

运行 yarn build

  • stylus

安装插件

yarn add stylus-loader stylus --dev

在webpack.config.base.js中配置

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
 devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[
new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)],
module: {
rules: [
      {
        test: /\.scss$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader',{
       loader:"sass-loader",
       options:{implementation:require('start-sass')}
}]
},
{
        test: /\.less$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader','less-loader']
},
{
        test: /\.stylus$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader','stylus-loader']
},
]},
}

运行 yarn build

webpack引入图片

安装插件

yarn add file-loader --dev

在webpack.config.base.js中配置

const path = require('path')
const Htmlwebpackplugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
   entry: {
      app: './src/index.js',
    },
    output: {
      filename: 'indx.[contenthash].js',
      path: path.resolve(__dirname, 'dist'),
    },
 devtool: 'inline-source-map',
    devServer: {
   contentBase: './dist',
 },
  plugin:[
new Htmlwebpackplugin({
         title: 'webpack'//html的标题
         template:'src/assets/index.html'//把自己最先生成好的HTML引入,通常情况自己建立的html放在src下的assets(资源)文件中
}
)],
module: {
rules: [
      {
        test: /\.scss$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader',{
       loader:"sass-loader",
       options:{implementation:require('start-sass')}
}]
},
{
        test: /\.less$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader','less-loader']
},
{
        test: /\.stylus$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['style-loader','css-loader','stylus-loader']
},
{
        test: /\.(png|svg|jpg|gif)$/,//这里使用到正则表达式。表示以.css文件结尾的
        use:['file-loader']
},
]},
}

运行 yarn build

懒加载

用import()去加载文件会得到一个promise,promise.then里面写成功做什么,失败做什么。

const button = document.createElement('button')
button.innerText = '懒加载'
button.claick =()=>{
const promise = import(./xxx.js)
promise.then(()=>{},()=>{})
}

发布于 2019-12-26 20:36