webpack4之路(2) - Loader
tips:上一篇文章我们已经一起学习了webpack的安装、打包与构建本地服务。现在我们一起学习Loader吧……
什么是loader?
在官网中loader的解释是对模块的源代码进行转换。loader 可以使你在 import
或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import
CSS文件!
安装配置css-loader
如果我们要加载一个css文件,需要先安装style-loader与css-loader
npm i style-loader css-loader -D // i是install的简称 -D表示生产环境使用
webpack.config.js
const path = require('path') module.exports = { mode: 'development', entry: { index: './scripts/index.js' // 入口文件,若不配置webpack4将自动查找src目录下的index.js文件 }, output: { filename: '[name].bundle.js', // 输出文件名,[name]表示入口文件js名 path: path.join(__dirname, 'dist') // 输出文件路径 }, devServer: { host: 'localhost', // 主机地址 compress: true, // 开发服务器是否启动gzip等压缩 contentBase: './dist',//开发服务运行时的文件根目录 open:true, // 自动打开浏览器 inline: true, port: 9000 // 监听的端口 }, module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 } ] } }
我们在webpack目录下新建style文件夹,并在文件夹内建立index.css文件
index.css
/* style.css */ body{ background: pink; }
在index.js中将它引入
import '../style/index.css' // 导入css let body = document.getElementsByTagName("body")[0] let div = document.createElement('div') div.innerText = 'init webpack' body.appendChild(div)
现在我们就可以检阅我们的成果了,npm run server.成功背景色已经变了。
配置sass
npm i sass-loader node-sass -D // 因为sass-loader依赖于node-sass,所以还要安装node-sass
在webpack.config.js新增sass的rules:
const path = require('path') module.exports = { mode: 'development', entry: { index: './scripts/index.js' // 入口文件,若不配置webpack4将自动查找src目录下的index.js文件 }, output: { filename: '[name].bundle.js', // 输出文件名,[name]表示入口文件js名 path: path.join(__dirname, 'dist') // 输出文件路径 }, devServer: { host: 'localhost', // 主机地址 compress: true, // 开发服务器是否启动gzip等压缩 contentBase: './dist',//开发服务运行时的文件根目录 open:true, // 自动打开浏览器 inline: true, port: 9000 // 监听的端口 }, module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.(scss|sass)$/, // 正则匹配以.scss或者.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 } ] } }
在style文件夹新建color.scss文件
/* color.scss */ $red: red; body { color: $red; }
在index.js文件中引入color.scss文件
import '../style/index.css' // 导入css import '../style/color.scss' // 导入scss let body = document.getElementsByTagName("body")[0] let div = document.createElement('div') div.innerText = 'init webpack' body.appendChild(div)
运行npm run server重新启动服务,就可以看到字体已经发生改变
类似图片loader、字体loader等使用也与css loader一样。官网有详细说明.
什么是Babel
npm i babel-core babel-loader babel-preset-env -D // babel-preset-env的env表示是对当前环境的预处理,而不是像以前使用babel-preset-es2015只能针对某个环境
在 webpack .config.js中,需要添加 babel-loader 等到 module 的 loaders 列表中
const path = require('path') module.exports = { mode: 'development', entry: { index: './scripts/index.js' // 入口文件,若不配置webpack4将自动查找src目录下的index.js文件 }, output: { filename: '[name].bundle.js', // 输出文件名,[name]表示入口文件js名 path: path.join(__dirname, 'dist') // 输出文件路径 }, devServer: { host: 'localhost', // 主机地址 compress: true, // 开发服务器是否启动gzip等压缩 contentBase: './dist',//开发服务运行时的文件根目录 open:true, // 自动打开浏览器 inline: true, port: 9000 // 监听的端口 }, module: { rules: [ { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.(scss|sass)$/, // 正则匹配以.scss或者.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.js$/, loader: ['babel-loader'], exclude: /node_modules/ // 不包括依赖内的js文件 } ] } }
上面的新增的配置,遇到JS文件就会先用babel-loader处理,exclude表示排除node_modules文件夹里的文件。loader配置就OK了,但是这样还不能发挥Babel的作用。要在项目根目录webpack文件夹下创建一个.babelrc文件,添加代码:
/* .babelrc 使用时把注释删掉,该文件不能添加注释*/ { "presets": [ "@babel/preset-env" ] }
当我们需要对项目中一些组件进行懒加载时,可以使用Babel的另一个插件
npm i babel-plugin-syntax-dynamic-import -D
在.babelrc文件中加入plugins配置:
/* .babelrc 使用时把注释删掉,该文件不能添加注释 */ { "presets": [ "@babel/preset-env" ], "plugins": [ "syntax-dynamic-import" ] }
在scripts文件夹创建helper.js
console.log('this is helper')
修改index.js
import '../style/index.css' // 导入css import '../style/color.scss' // 导入scss const App = function () { let div = document.createElement('div') div.setAttribute('id', 'app') document.body.appendChild(div) let dom = document.getElementById('app') dom.innerHTML = 'init webpack' let button = document.createElement('button') button.innerText = 'click me' button.onclick = () => { const help = () => import('./helper') help() } document.body.appendChild(button) } const app = new App()
然后进行打包npm run server,报错 了
提示在依赖里找不到babel-core 。这是个大坑,至少我被坑了很久。最后开始去百度找到解决方案有两种
npm i babel-loader@7 babel-core babel-preset-env -D // 回退低版本 npm i babel-loader @babel/core @babel/preset-env webpack -D // 更新到最高版本
反正我反复重新安装依赖,都是各种报错。最后终于明白了原因是:
babel-loader和babel-core版本不对应所产生的,
- babel-loader 8.x对应babel-core 7.x
- babel-loader 7.x对应babel-core 6.x
最后给大家看下我的package.json就有种恍然大悟的感觉
{ "name": "webpack_demo", "version": "1.0.0", "description": "my first webpack", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "server": "webpack-dev-server --mode development " }, "author": "", "license": "ISC", "dependencies": { "neo-async": "^2.6.1", "save-dev": "0.0.1-security" }, "devDependencies": { "@babel/core": "^7.8.7", "@babel/preset-env": "^7.8.7", "babel-loader": "^8.0.4", "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-preset-env": "^1.7.0", "css-loader": "^3.4.2", "html-webpack-plugin": "^3.2.0", "loader-runner": "^3.1.0", "node-sass": "^4.13.1", "sass-loader": "^8.0.2", "style-loader": "^1.1.3", "webpack": "^4.42.0", "webpack-cli": "^3.3.11", "webpack-dev-server": "^3.10.3" } }
之前我的babel-loader一直是7的版本,后来升级到8的版本就解决了此问题。真是无比开心~~~~
来查看我们刚刚配置的bable有没有成功吧
还记得我们之前写的点击事件是ES6的箭头函数吧。现在已变成ES5的语法,证明已经使用成功。
查阅资料:
1)https://www.jianshu.com/p/74cb6203c39f (Cannot find module '@babel/core’)
2)https://segmentfault.com/a/1190000017898866(babel-loader使用)
3)https://www.cnblogs.com/BetterMan-/p/9867642.html (webpack 4X学习)
4)https://www.webpackjs.com/loaders/babel-loader/ (loader官网介绍)