webpack 学习笔记1(入门)
由于笔者的nodejs版本比较新,所以用webpack4会有一些bug。因此直接选择了webpack5
版本: node -v #v18.15.0
#1 安装
采用本地安装,没有全局安装。因为不同的项目可能使用的webpack版本不同,所以全局安装会有一些问题。还是一个项目一个版本比较好。
#由于本地无通过webpack -v ;webpack-cli -v 查看版本,不过可以直接在package.json里看到版本
npm install -D webpack #@5.78.0
npm install -D webpack-cli #@5.0.1
#2 一个极其简单的例子
先写一个webpack.config.js文件,将login模块打包到build中
const path = require('path');
module.exports = {
entry: {
"login":"./data/login.js"},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'build2'),
clean: true//自动删除之前的文件
}
};
然后写login代码(以及调用到的js的代码)
//login.js
const name = require("./name")
console.log("abc_log:",name);
//name.js module.exports="jack";
使用npm init初始化package.json文件,过程中选择webpack.config.js文件作为配置文件。
注意在script中需要添加"build":"webpack xxxxxxx",因为webpack非全局安装,所以cmd中webpack命令无法直接使用。通过此方法然后调用 npm run build 就可以运行webpack了。
如果不使用scripts的形式。直接打包使用命令 npx webpack --mode=development
{
"name": "html",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build":"webpack --mode=development",
"pro":"webpack --mode=production"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.78.0",
"webpack-cli": "^5.0.1"
}
}
此时就生成了login.js的文件,如下(经过编码的,不过还是可以看到一些关键字):
(()=>{var o={341:o=>{o.exports="jack"}},r={};function t(e){var s=r[e];if(void 0!==s)return s.exports;var n=r[e]={exports:{}};return o[e](n,n.exports,t),n.exports}(()=>{const o=t(341);console.log("abc_log:",o)})()})();
至此一个最最简单的实例就完成了。大的框架由此开始编写!
#3. 用html-webpack-plugin,从模板html生成目标html
npm install -D html-webpack-plugin #笔者的版本是@5.5.0
然后新建一个tpl.html模板如下:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,maximum-scale=1" />
<!--常用库写这里,.........-->
<!-- 这里的titile在config.js中设置-->
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="content"></div>
</body>
</html>
webpack.config.js新增配置如下:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const dist = "../../nginx-1.22.1/nginx-1.22.1/html/data";
module.exports = {
entry:{
"investors_shares":"./data/investors_shares.js"
},
output: {
filename: '[name].[chunkhash].js',//模块名字+MD5
path: path.resolve(__dirname, dist),
clean: true//自动删除之前的文件
},
plugins:[
new HtmlWebpackPlugin({
title: "XXX",
filename: "investors_shares.html",//目标文件
template: "./data/tpl.html",//源文件
inject: "body",//插入到body元素后
minify:{
removeComments:true//移除HTML中的注释
},
chunks:["investors_shares","XXX"]//这里制定引入哪些js,如果不写,则默认引入html同名的
}),
]
};
运行npm run build后,生成一个js和一个html文件。可以直接用浏览器查看输出

#4 安装react react-dom 以及babel相关
npm i -D react@15.4.2 react-dom@15.4.2 babel-loader @babel/core @babel/preset-env @babel/preset-react
笔者的最终安装版本如下:
"devDependencies": {
"@babel/core": "^7.21.4",
"@babel/preset-env": "^7.21.4",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^9.1.2",
"react": "^15.4.2",
"react-dom": "^15.4.2",
。。。
这里略作解释(参考http://events.jianshu.io/p/822b8cc0fb4e):
babel-loader:使用Babel转换JavaScript依赖关系的Webpack加载器, 简单来讲就是webpack和babel中间层,允许webpack在遇到js文件时用bable来解析
@babel/core:即babel-core,将ES6代码转换为ES5。7.0之后,包名升级为@babel/core。@babel相当于一种官方标记,和以前大家随便起名形成区别。
@babel/preset-env:即babel-preset-env,根据您要支持的浏览器,决定使用哪些transformations / plugins 和 polyfills,例如为旧浏览器提供现代浏览器的新特性。
@babel/preset-react:即 babel-preset-react,针对所有React插件的Babel预设,例如将JSX转换为函数.
编写webpack.config.js如下,新增了rules部分,如下:
XXX
output: {
XXX
},
module: {
rules: [
{
test: /\.js|jsx$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: "defaults" }],
['@babel/preset-react']
]
}
}
}
]
},
plugins:[
XXX
js部分如下随便添加一些代码:
let React = require('react');
let ReactDOM = require('react-dom');
let gf = require("./gf")
class Index extends React.Component{
constructor(props) {
super(props);
this.state = {};
}
componentWillMount() { }
componentDidMount() { }
render () {
return(
<div>{gf.DOMAIN+"javamy"}</div>
);
}
}
ReactDOM.render(
<Index />,
document.getElementById('content')
);
gf.js如下
module.exports = {
fun:(name)=>{
return jack;
},
DOMAIN : '//' + location.host + '/api'
}
运行npm run build,就生成了一个很大的XX.js文件。此时这个文件是将react,jquery等代码的代码都组装到里面了,具体没研究。后续肯定要分离开,不然没法复用公共库了。
# 5如何在webpack中使用jquery
最简单的方法就是在html中将jquery的文件引入进来,然后直接调用即可。本文这里所想实现的(或者说学习的)是将jquery进入到工程模块,一并打包。
这个时候就需要首先安装jquery
npm install --save jquery
#这里其实用--save-dev也可以,因为只要improt了并使用了的函数或者库,不管他是devDependencies或者dependencies里都会进行打包处理。具体参看:https://zhuanlan.zhihu.com/p/215887185
#这种与nodejs做后端用的express框架那种不一样。
然后在js代码中引入jquery
import $ from 'jquery';
//或者使用 var $ = require("jquery");
$.ajax({
url: gf.DOMAIN+'api/getuserinfo',
type: 'GET',
xhrFields: {withCredentials: true},
cache:false,
data: {},
。。。。。
这是时候用npm run build会发现最终的js包变大了很多,就是把jquery代码也写进去了。当然也可以将公共库分离出来避免多个页面的js多次重复打包
#在webpack5中使用css sass scss
npm install --save-dev style-loader css-loader sass-loader sass #笔者版本为css-loader@6.7.3 sass-loader@13.2.2 style-loader@3.3.2 sass@1.62.0
css-loader: 把 css 文件编译为 CommonJS 模块,并将该模块引入到 JS 中。
style-loader:创建 <style>标签,将 JS 中的 CSS 添加到 HTML中。
sass-loader、sass:不解释。
webpack.config.js中rules中增加如下:
module: {
rules: [
...
{
test: /\.s?[ca]ss$/, //sass 或者scss css
use: [//加载顺序是从后先做,即先sass-loader,再css-loader,最后style-loader。
'style-loader',//style-loader是将css放置到页面上
'css-loader',
'sass-loader',
]
}
]
},
新建一个app.scss文件
.app-frame {
margin: auto;
width: 100%;
max-width: 1000px;
}
app.js中引入文件
import './app.scss'
。。。
。。。
render () {
return(
<div className='app-frame'></div>
);
}
}
ReactDOM.render(
<Index />,
document.getElementById('content')
npm run build后,刷新页面直接生效
#在webpack5中使用BootStrap
参考https://getbootstrap.com/docs/4.0/getting-started/webpack/
npm install --save bootstrap@4.6.2 jquery popper.js #注意popper后面必须有.js,原因不知。popper的版本为1.16.1。
#使用bootstrap必须安装popper.js和jquery。不过笔者经过实验,对于bootstrap4.6.2版本,其安装的时候,会将popper.js和jquery默认进行安装。所以其实只需要install --save bootstrap@4.6.2即可
根据 https://v4.bootcss.com/docs/getting-started/introduction/ 可知,一般bootstrap有2中调用依赖关系,本节使用的是第二种,即插件独立:
<!-- Bootstrap 的 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
。。。
<!-- JavaScript 文件是可选的。从以下两种建议中选择一个即可! -->
<!-- 选项 1:jQuery 和 Bootstrap 集成包(集成了 Popper) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
<!-- 选项 2:Popper 和 Bootstrap 的 JS 插件各自独立 -->
<!--
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.min.js" integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+" crossorigin="anonymous"></script>
-->
</body>
js代码中引入bootstrap,根据文档(和实际实验)popper.js和jquery不需要手动引入
//import 'popper.js'
//import 'jquery' import 'bootstrap'
app.scss中直接引入bootstrap的s?[ca]ss文件如下:(当然在app.js中直接import也行)
//app.scss
。。。。$lightGrayColor:#eee;
@import '~bootstrap/scss/bootstrap';
.app-frame {
ma。。。。
#devtool的配置
Webpack里有个配置项叫做devtool,这个配置项主要是用于配置打包后的代码映射,方便我们在debug的时候查看到源代码的位置,主要是发生异常错误的时候,可以定位到准确位置。
output: {
XXX
},
module: {
rules: [
{
}
]
},
devtool: 'inline-source-map',//如果是生产环境,用'source-map'
plugins:[
XXX
在生产环境,一般使用'source-map',此时js的包会比没有devtool的时候大一些,而且多了要给*.map文件。浏览器就是通过这个map定位到错误。如果是在生产环境使用'inline-source-map',操作上也可以,但是那么js文件会很大,所以极其不推荐。
在开发环境,按照官方推荐,一般使用'inline-source-map'。虽然有source-map,但是也有inline字段,所以这个时候,也是生产一个map文件内容对应的base64插入到*.js里面去。操作上,也可以使用'source-map',只是一边使用'inline-source-map'。
#文件引入file-loader(图片,附件等)
file-loader可以协助在webpack中引入图片等。
npm install --save-dev file-loader //@6.2.0
在配置文件中
module: {
rules: [
{
test: /\.js|jsx$/,
XXX
},
{
test: /\.(png|svg|jpg|ico|gif|bmp|pdf|jpe?g)$/,
use: [
{
loader:'file-loader',
options:{
name:'[name].[ext]',
outputPath:'img'//会输出到dist下的img文件夹
}
}
]
},
]
},
plugins:[
js文件中的代码这样写:
import logo from './img/cil-notes.svg';
<img height='100%' src={logo} />
注:与file-loader对应常用的loader是已下3个,本文只涉及到file-loader:
raw-loader 将文件导入为字符串
url-loader 将文件作为 data URI 内联到 bundle 中
file-loader 将文件发送到输出目录
然而在webpack5开始,不建议使用以上3个了,而改用以下的形式【https://www.webpackjs.com/guides/asset-modules/#root】:
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
asset/resource发送一个单独的文件并导出 URL。之前通过使用file-loader实现。asset/inline导出一个资源的 data URI。之前通过使用url-loader实现。asset/source导出资源的源代码。之前通过使用raw-loader实现。asset在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用url-loader,并且配置资源体积限制实现。
当在 webpack 5 中使用旧的 assets loader(如 file-loader/url-loader/raw-loader 等)和 asset 模块时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为 'javascript/auto' 来解决。
具体用法参考下一篇文章:webpack 学习笔记2(进阶)
XXX
XX

浙公网安备 33010602011771号