繁体   English   中英

如何将 babel 和 webpack 实现更新和整合到当前的最佳实践中? (错误:找不到模块“@babel/core”)

[英]How to update and consolidate babel and webpack implementations to current best practices? (Error: Cannot find module '@babel/core')

期望的行为

  • 运行webpackbabel没有任何错误
  • 确保我以最佳/最有效的方式使用 webpack 和 babel
  • 更好地理解 webpack 和 babel 是如何工作的(而不是仅仅复制粘贴代码来工作)

语境:

我正在更新几年前的一个项目,因此我之前使用的约定和包已被取代,我想让我的实现符合当前的最佳实践。

实际行为

我刚刚更新了节点( v14.18.1 )和我所有的 npm 包。

运行时:

npm run webpack

我收到错误:

(node:18300) [DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING] DeprecationWarning: Using a string as loader options is deprecated (ruleSet[1].rules[4].use[0].options)
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:18300) [DEP_WEBPACK_MAIN_TEMPLATE_HASH_FOR_CHUNK] DeprecationWarning: MainTemplate.hooks.hashForChunk is deprecated (use JavascriptModulesPlugin.getCompilationHooks().chunkHash instead)
(node:18300) [DEP_WEBPACK_CHUNK_TEMPLATE_HASH_FOR_CHUNK] DeprecationWarning: ChunkTemplate.hooks.hashForChunk is deprecated (use JavascriptModulesPlugin.getCompilationHooks().chunkHash instead)
(node:18300) [DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS] DeprecationWarning: optimizeChunkAssets is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)
(node:18300) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET_LENGTH] DeprecationWarning: chunk.files was changed from Array to Set (using Array property 'length' is deprecated)
(node:18300) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET_INDEXER] DeprecationWarning: chunk.files was changed from Array to Set (indexing Array is deprecated)
assets by status 2.63 KiB [cached] 1 asset
./src/js/common.js 39 bytes [not cacheable] [built] [code generated] [1 error]

ERROR in ./src/js/common.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find module '@babel/core'
Require stack:
- D:\REPOS\my application\node_modules\babel-loader\lib\index.js
- D:\REPOS\my application\node_modules\loader-runner\lib\loadLoader.js
- D:\REPOS\my application\node_modules\loader-runner\lib\LoaderRunner.js
- D:\REPOS\my application\node_modules\webpack\lib\NormalModuleFactory.js
- D:\REPOS\my application\node_modules\webpack\lib\Compiler.js
- D:\REPOS\my application\node_modules\webpack\lib\webpack.js
- D:\REPOS\my application\node_modules\webpack\lib\index.js
- D:\REPOS\my application\node_modules\webpack-cli\lib\webpack-cli.js
- D:\REPOS\my application\node_modules\webpack-cli\lib\bootstrap.js
- D:\REPOS\my application\node_modules\webpack-cli\bin\cli.js
- D:\REPOS\my application\node_modules\webpack\bin\webpack.js
 babel-loader@8 requires Babel 7.x (the package '@babel/core'). If you'd like to use Babel 6.x ('babel-core'), you should install 'babel-loader@7'.  

我如何摆脱上述错误,并在这样做时整合我当前的 babel/webpack 实现以使用当前的最佳实践?

可能的解决方案

这篇文章的答案,似乎得到了官方 babel 文档的支持,包括:

删除被取代的包,例如:

npm uninstall babel-core babel-cli babel-preset-env babel-preset-stage-0     

安装新软件包,例如:

npm install --save-dev @babel/core @babel/cli @babel/preset-env

我犹豫要不要这样做,因为:

  • 我当前在package.json中的devDependencies是:
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-loader": "^8.2.3",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-0": "^6.24.1",
"css-loader": "^6.5.0",
"expose-loader": "^3.1.0",
"file-loader": "^6.2.0",
"jsdoc": "^3.6.7",
"less": "^4.1.2",
"less-loader": "^10.2.0",
"style-loader": "^3.3.1",
"uglifyjs-webpack-plugin": "^2.2.0",
"uikit": "^3.8.0",
"url-loader": "^4.1.1",
"webpack": "^5.61.0",
"webpack-cli": "^4.9.1"
  • 我的webpack.config.json文件引用babel-loaderoptions: { presets: ["env", "stage-0"] } webpack.config.json options: { presets: ["env", "stage-0"] }

  • 我有一个.babelrc文件

所以我不确定对devDependencies更改devDependencies会弄乱webpackbabelrc配置。

我试过的

Part 01: 定义相关文件和逻辑

以下是我项目中与 babel 和 webpack 相关的不同文件:

  • index.ntl (引用bundle.js html 模板)
  • app_es6.js (ES6 中的服务器端代码,由 babel 转译/输出到app.js
  • app.js (babel 生成的服务器端代码)
  • common.js (浏览器端代码,与其他资源bundle.js被 webpack 组合成 bundle.js)
  • bundle.js (由 webpack 生成的浏览器端代码)
  • package.json
  • .babelrc
  • webpack.config.js

如果我对自己的package.jsonwebpack.config.js文件的理解是正确的('我对这个地方没有记忆' - gandalf meme),我认为 webpack 仅适用于浏览器端代码( common.js - 配置在webpack.config.js中定义),而 babel 仅专门应用于服务器端代码( app_es6.js - 配置在.babelrc中定义)。

webpack.config.js引用了以下加载器

babel-loader - 使用 Babel 加载 ES2015+ 代码并转换为 ES5
style-loader - 将模块的导出作为样式添加到 DOM
css-loader - 加载具有解析导入的 CSS 文件并返回 CSS 代码
less-loader - 加载和编译 LESS 文件
url-loader - 将文件转换为 base64 URI
暴露加载器- 将模块全部或部分暴露给全局对象

以下是相关文件的内容:

索引.ntl

<script src="/js/bundle.js"></script>

.babelrc

{
    "presets": [
        [
            "env",
            {
                "targets":
                {
                    "node": "current"
                }
            }
        ]
    ]
}

webpack.config.js

const path = require('path');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); 

var webpack = require("webpack");

module.exports = {
    mode: "production", 
    entry: "./src/js/common.js",  // <------ for browser-side code
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "dist/js")
    },
    module: {
        rules: [{
                test: /\.js$/,
                exclude: /(node_modules)/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: ["env", "stage-0"]
                    }
                }
            },
            {
                test: /\.css$/,
                use: [
                    { loader: "style-loader" },
                    { loader: "css-loader" }
                ]
            },
            {
                test: /\.less$/,
                use: [
                    { loader: "style-loader" },
                    { loader: "css-loader" },
                    { loader: "less-loader" }
                ]
            },
            {
                test: /\.jpg$/,
                use: [
                    { loader: "url-loader" }
                ]
            },
            {
            test: require.resolve('jquery'),
            use: [{
            loader: 'expose-loader',
            options: '$'
            }]
            },
            {
            test: require.resolve('js-cookie'),
            use: [{
            loader: 'expose-loader',
            options: 'Cookies'
            }]
            },
            {
            test: require.resolve('he'),
            use: [{
            loader: 'expose-loader',
            options: 'he'
            }]
            }
        ]
    },
    plugins: [
       new UglifyJsPlugin(),
       new webpack.ProvidePlugin({
            $: "jquery",  
            jQuery: "jquery",
            'window.jQuery': 'jquery'
        })
    ],
    resolve: {
    alias: {
        'uikit-util': path.resolve(__dirname, 'node_modules/uikit/src/js/util')
    }
    }
}

包.json

{
  //...
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "build-server-file": "babel app_es6.js --out-file app.js",   // <------ for server-side code  
    "webpack": "webpack"  // <------ for browser-side code 
  },
  //... 
  "dependencies": {
  //...
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.3",
    "babel-loader": "^8.2.3",
    "babel-preset-env": "^1.7.0",
    "babel-preset-stage-0": "^6.24.1",
    "css-loader": "^6.5.0",
    "expose-loader": "^3.1.0",
    "file-loader": "^6.2.0",
    "jsdoc": "^3.6.7",
    "less": "^4.1.2",
    "less-loader": "^10.2.0",
    "style-loader": "^3.3.1",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "uikit": "^3.8.0",
    "url-loader": "^4.1.1",
    "webpack": "^5.61.0",
    "webpack-cli": "^4.9.1"
  }
}

第 02 部分:研究

为了加深我对 babel、webpack 和 loader 的理解:

问: babel 有什么作用?

Babel 是一个工具链,主要用于在当前和旧浏览器或环境中将 ECMAScript 2015+ 代码转换为向后兼容的 JavaScript 版本

来源: https : //babeljs.io/docs/en

问:为什么我需要 babel?

因为 node.js 还不能读取 ES6 (?)

问: webpack 有什么作用?

从本质上讲,webpack 是现代 JavaScript 应用程序的静态模块打包器。 当 webpack 处理您的应用程序时,它会从一个或多个入口点在内部构建一个依赖关系图,然后将您的项目需要的每个模块组合成一个或多个包,这些包是静态资产来为您的内容提供服务。

来源: https : //webpack.js.org/concepts

问:什么是 webpack 加载器?

加载器是应用于模块源代码的转换。 它们允许您在导入或“加载”文件时对文件进行预处理。 因此,加载器有点像其他构建工具中的“任务”,并提供了一种处理前端构建步骤的强大方法。 加载器可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内嵌图像加载为数据 URL。 加载器甚至允许你直接从你的 JavaScript 模块导入 CSS 文件!

来源: https : //webpack.js.org/concepts/loaders

问:什么是module.rules

module.rules允许您在 webpack 配置中指定多个加载器。 这是显示加载器的简洁方式,有助于维护干净的代码。 它还为您提供每个加载器的完整概述。

来源: https : //webpack.js.org/concepts/loaders/#configuration

问:为什么我需要 webpack?

我主要使用 webpack 来丑化和缩小我的浏览器端代码,并将我所有的 JavaScript、CSS、Less 和图像文件合并到一个index.ntl引用的bundle.js文件中——这提高了性能和安全性(?)

另见文章:为什么使用 webpack

进一步阅读

https://babeljs.io/docs/en/usage
https://babeljs.io/docs/en/configuration
https://scotch.io/tutorials/javascript-transpilers-what-they-are-why-we-need-them

以下步骤已消除所有错误。

01)运行:

npm uninstall babel-core babel-cli babel-preset-env babel-preset-stage-0

02)运行:

npm install --save-dev @babel/core @babel/cli @babel/preset-env

按照官方文档:

https://babeljs.io/docs/en/usage#overview

03)webpack.config.json ,改变这个:

module: {
    rules: [{
            test: /\.js$/,
            exclude: /(node_modules)/,
            use: {
                loader: "babel-loader",
                options: {
                    presets: ["env", "stage-0"]
                }
            }
        },
        {
            test: /\.css$/,
            use: [
                { loader: "style-loader" },
                { loader: "css-loader" }
            ]
        },
        {
            test: /\.less$/,
            use: [
                { loader: "style-loader" },
                { loader: "css-loader" },
                { loader: "less-loader" }
            ]
        },
        {
            test: /\.jpg$/,
            use: [
                { loader: "url-loader" }
            ]
        },
        {
            test: require.resolve('jquery'),
            use: [{
                loader: 'expose-loader',
                options: '$'
            }]
        },
        {
            test: require.resolve('js-cookie'),
            use: [{
                loader: 'expose-loader',
                options: 'Cookies'
            }]
        },
        {
            test: require.resolve('he'),
            use: [{
                loader: 'expose-loader',
                options: 'he'
            }]
        }
    ]
}

对此:

module: {
    rules: [{
            test: /\.js$/,
            exclude: /(node_modules)/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-env']
                }
            }
        },
        {
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
        },
        {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
        },
        {
            test: /\.jpg$/,
            use: ['url-loader']
        },
        {
            test: require.resolve('jquery'),
            loader: 'expose-loader',
            options: {
                exposes: ['$']
            }
        },
        {
            test: require.resolve('js-cookie'),
            loader: 'expose-loader',
            options: {
                exposes: ['Cookies']
            }
        },
        {
            test: require.resolve('he'),
            loader: 'expose-loader',
            options: {
                exposes: ['he']
            }
        }
    ]
}

以下是各种用法示例:

https://webpack.js.org/loaders

04).babelrc重命名为.babelrc.json并更改其内容:

{
    "presets": [ [ "env", { "targets": { "node": "current" } } ] ]
}

对此:

{
  "presets": ["@babel/preset-env"]
}

遵循这些示例:

https://babeljs.io/docs/en/configuration#babelrcjson
https://github.com/babel/example-node-server

并通过此答案告知:

https://stackoverflow.com/a/52435686

05)我的浏览器端文件common.js中的几个导入语句导致错误,我更改了:

由此:

import getYear from 'date-fns/get_year';
import getMonth from 'date-fns/get_month';
import getDaysInMonth from 'date-fns/get_days_in_month';
import startOfMonth from 'date-fns/start_of_month';
import getDay from 'date-fns/get_day';
import format from 'date-fns/format';

对此:

import { getYear, getMonth, getDaysInMonth, startOfMonth, getDay, format} from 'date-fns';

由此:

import { saveAs } from 'file-saver/FileSaver';

对此:

import { saveAs } from 'file-saver';

由此:

import io from 'socket.io-client';

对此:

import { io } from 'socket.io-client'
/* 
also had to do: 
npm install socket.io-client  
(and not just socket.io)   
*/ 

由此:

import input_validator from './my_modules/input_validator';

对此:

import { input_validator } from './my_modules/input_validator';
/*
also had to change export from this:  
module.exports = input_validator;  
to this:  
export { input_validator };
*/

06)为了摆脱less-loader的错误,在webpack.config.js ,我改变了这个:

{
    test: /\.less$/,
    use: ['style-loader', 'css-loader', 'less-loader']
}

对此:

{
    test: /\.less$/,
    // use: ['style-loader', 'css-loader', 'less-loader']
    use: [
    {
        loader: "style-loader",
    },
    {
        loader: "css-loader",
    },
    {
        loader: "less-loader",
        options:
        {
            lessOptions:
            {
                math: "always",
            },
        },
    }, ]
}

作为参考,仍然有弃用警告:

(node:22060) [DEP_WEBPACK_MAIN_TEMPLATE_HASH_FOR_CHUNK] DeprecationWarning: MainTemplate.hooks.hashForChunk is deprecated (use JavascriptModulesPlugin.getCompilationHooks().chunkHash instead)
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:22060) [DEP_WEBPACK_CHUNK_TEMPLATE_HASH_FOR_CHUNK] DeprecationWarning: ChunkTemplate.hooks.hashForChunk is deprecated (use JavascriptModulesPlugin.getCompilationHooks().chunkHash instead)
(node:22060) [DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS] DeprecationWarning: optimizeChunkAssets is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)  
(node:22060) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET_LENGTH] DeprecationWarning: chunk.files was changed from Array to Set (using Array property 'length' is deprecated)
(node:22060) [DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET_INDEXER] DeprecationWarning: chunk.files was changed from Array to Set (indexing Array is deprecated)  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM