webpack4之路(2)

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

babel是一个JS编译器,用来转换最新的JS语法,比如把ES6, ES7等语法转化成ES5语法,从而能够在大部分浏览器中运行。像箭头函数,就可以做转换。babel在执行过程中,分三步:先分析(parsing)、再转化、最后生成代码。
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官网介绍)

原文地址:https://www.cnblogs.com/yilihua/p/12494927.html