简体   繁体   English

Webpack 3 + babel仅在条目不高于./webpack.config.js时进行解析

[英]Webpack 3 + babel only parsing when entry is NOT higher than ./webpack.config.js

I'm building a scaffolding engine to spin up Django-backend + React-frontend sites. 我正在构建一个脚手架引擎来启动Django后端+ React前端站点。 I'm also taking a multi-page app approach, instead of an SPA, so things are a bit... unorthodox. 我还采用了多页应用程序方法,而不是SPA,所以事情有点...不合常规。

I'm showing you the end result of that scaffolding because the problem seems to be with my webpack or babel configuration, and the location of the input component I give them. 我向您展示该脚手架的最终结果,因为问题似乎出在我的webpack或babel配置以及我给他们的输入组件的位置。

So first, this file structure DOES work, the react component renders beautifully on Django's server. 因此,首先,此文件结构确实起作用,react组件在Django的服务器上呈现精美。

node/
    package.json
    .babelrc
    webpack.config.js
    /src
        /Home.js (<- the react component)
    ...
www/
    manage.py
    www/
         templates/
             home.html
         dist/
             home.js (<- webpack's output)
...

But I would prefer it like this, where the component is closer to the django template.html file: 但是我更喜欢这样,其中组件更靠近django template.html文件:

node/
    package.json
    .babelrc
    webpack.config.js
    ...
www/
    manage.py
    www/
         templates/
             home.html
             react/
                  components/
                  containers/
                      Home.js (<- the react component)
         dist/
             home.js (<- webpack's output)

However, I now get a build error where it complains when it sees the JSX - as if babel didn't polyfill it at all. 但是,我现在收到一个构建错误,当它看到JSX时会抱怨-好像babel根本没有将其填充。

The only thing I changed is that the component is no longer under the node/ directory (and obviously I updated the path in webpack.config.js to reflect that) 我唯一更改的是该组件不再位于node /目录下(显然,我更新了webpack.config.js中的路径以反映这一点)

I don't think it's a matter of webpack finding the right path. 我认为这不是webpack找到正确路径的问题。 Because it IS reading the component in the templates dir, and it's still putting the bundle correctly in the dist dir. 因为它正在读取模板目录中的组件,并且仍将分发包正确放置在dist目录中。 But it's not polyfilling, and the resulting output file is broken. 但这不是polyfilling,结果输出文件已损坏。 I don't just mean it's uglified, I mean it's completely broken (see below) 我不只是说它被丑化了,我是说它已经完全坏掉了(见下文)

Is it even possible to do what I'm trying to do? 甚至有可能做我想做的事情?

Details 细节

The error when I run 'npm run build' to run webpack: 当我运行'npm run build'来运行webpack时出现错误:

ERROR in ../www/www/templates/react/containers/HomeContainer.js
Module build failed: SyntaxError: Unexpected token (6:2)

  4 | const Home = props => {
  5 |   return (
> 6 |       <div>

babelrc babelrc

{
    "presets": ["env", "react"]
}

webpack.config.js webpack.config.js

const webpack = require('webpack'); //to access built-in plugins
const path = require('path');

// This one works
// let ent = "./HomeContainer.js"

// This one does NOT work
let ent = "../www/www/templates/react/containers/HomeContainer.js"

let out = "../www/www/static/dist/js/Home"

module.exports = {
    entry: {
        [out]: ent
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, './'),
    },
    module: {
        rules: [
            { test: /\.css$/,  exclude: /node_modules/, use: 'css-loader' },
            { test: /\.scss$/, exclude: /node_modules/, use: 'sass-loader' },
            { test: /\.(js|jsx)$/, exclude: /node_modules/, loader: "babel-loader" }
        ],
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin(),
    ],
}

package.json 的package.json

{
    "name": "frontend",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo 'Error: no test specified' && exit 1",
        "build": "webpack"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "babel-cli": "^6.24.1",
        "babel-core": "^6.25.0",
        "babel-loader": "^7.1.1",
        "babel-preset-env": "^1.6.0",
        "babel-preset-react": "^6.24.1",
        "css-loader": "^0.28.4",
        "node-sass": "^4.5.3",
        "sass-loader": "^6.0.6",
        "webpack": "^3.1.0"
    },
    "dependencies": {
        "react": "^15.6.1",
        "react-dom": "^15.6.1"
    }
}

The broken dist/home.js 损坏的dist / home.js

!function(m){function t(e){if(n[e])return n[e].exports;var r=n[e]={i:e,l:!1,exports:{}};return m[e].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};t.m=m,t.c=n,t.d=function(m,n,e){t.o(m,n)||Object.defineProperty(m,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(m){var n=m&&m.__esModule?function(){return m.default}:function(){return m};return t.d(n,"a",n),n},t.o=function(m,t){return Object.prototype.hasOwnProperty.call(m,t)},t.p="",t(t.s=0)}([function(m,t){throw new Error("Module build failed: SyntaxError: Unexpected token (6:2)\n\n[0m [90m 4 | [39m[36mconst[39m [33mHome[39m [33m=[39m props [33m=>[39m {\n [90m 5 | [39m\t[36mreturn[39m (\n[31m[1m>[22m[39m[90m 6 | [39m\t\t[33m<[39m[33mdiv[39m[33m>[39m\n [90m   | [39m\t\t[31m[1m^[22m[39m\n [90m 7 | [39m\t\t\t[33m<[39m[33mh1[39m[33m>[39m[33mHome[39m page [36mfor[39m { window[33m.[39mprops[33m.[39mproject_title }[33m<[39m[33m/[39m[33mh1[39m[33m>[39m\n [90m 8 | [39m\t\t\t[33m<[39m[33mp[39m[33m>[39m[33mTo[39m edit [36mthis[39m page[33m,[39m you[32m'll find the react component at /frontend/src/root/Home.js</p>[39m\n [90m 9 | [39m\t\t[33m<[39m[33m/[39m[33mdiv[39m[33m>[39m[0m\n")}]);

The dist/home.js that does work 起作用的dist / home.js

!function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=81)}([function(e,t){function n(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function r(e){if(l===setTimeout)return setTimeout(e,0);if((l===n||!l)&&setTimeout)return l=setTimeout,setTimeout(e,0);try{return l(e,0)}catch(t){try{return l.call(null,e,0)}catch(t){return l.call(this,e,0)}}}function i(e){if(p===clearTimeout)return clearTimeout(e);if((p===o||!p)&&clearTimeout)return p=clearTimeout,clearTimeout(e);try{return p(e)}catch(t){try{return p.call(null,e)}catch(t){return p.call(this,e)}}}function a(){m&&f&&(m=!1,f.length?h=f.concat(h):v=-1,h.length&&s())}function s(){if(!m){var e=r(a);m=!0;for(var t=h.length;t;){for(f=h,h=[];++v<t;)f&&f[v].run();v=-1,t=h.length}f=null,m=!1,i(e)}}function u(e,t){this.fun=e,this.array=t}function c(){}var l,p,d=e.exports={};!function(){try{l="function"==typeof setTimeout?setTimeout:n}catch(e){l=n}try{p="function"==typeof clearTimeout?clearTimeout:o}catch(e){p=o}}();var f,h=[],m=!1,v=-1;d.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];h.push(new u(e,t)),1!==h.length||m||r(s)},u.prototype.run=function(){this.fun.apply(null,this.array)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.versions={},d.on=c,d.addListener=c,d.once=c,d.off=c,d.removeListener=c,d.removeAllListeners=c,d.emit=c,d.prependListener=c,d.prependOnceListener=c,d.listeners=function(e){return[]},d.binding=function(e){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(e){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}},function(e,t,n){"use strict";(function(t){function n(e,t,n,r,i,a,s,u){if(o(t),!e){var c;if(void 0===t)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,i,a,s,u],p=0;c=new Error(t.replace(/%s/g,function(){return l[p++]})),c.name="Invariant Violation"}throw c.framesToPop=1,c}}var o=function(e){};"production"!==t.env.NODE_ENV&&(o=function(e){if(void 0===e)throw new Error("invariant requires an error message argument")}),e.exports=n}).call(t,n(0))},function(e,t,n){"use strict";(function(t){var o=n(9),r=o;if("production"!==t.env.NODE_ENV){var i=function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),o=1;o<t;o++)n[o-1]=arguments[o];var r=0,i="Warning: "+e.replace(/%s/g,function(){return n[r++]});"undefined"!=typeof console&&console.error(i);try{throw new Error(i)}catch(e){}};r=function(e,t){if(void 0===t)throw new Error("`warning(condition, format, ...args)` requires a warning message argument");if(0!==t.indexOf("Failed Composite propType: ")&&!e){for(var n=arguments.length,o=Array(n>2?n-2:0),r=2;r<n;r++)o[r-2]=arguments[r];i.apply(void 0,[t].concat(o))}}}e.exports=r}).call(t,n(0))},function(e,t,n){"use strict";function o(e){for(var t=arguments.length-1,n="Minified React error #"+e+"; visit http://facebook.github.io/react/docs/error-decoder.html?invariant="+e,o=0;o<t;o++)n+="&args[]="+encodeURIComponent(arguments[o+1]);n+=" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";var r=new Error(n);throw r.name="Invariant Violation",r.framesToPop=1,r}e.exports=o},function(e,t,n){"use strict";function o(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}/*

The issue is that Babel looks for a .babelrc closest to the file that is being transpiled . 问题是Babel会寻找最接近要.babelrc文件的.babelrc That means it looks in the directory of the file and starts climbing up the directory tree until it finds one or reaches the root of the file system. 这意味着它将在文件目录中查找并开始爬升目录树,直到找到一个或到达文件系统的根目录为止。 But as your node directory is a sibling of www , where your sources are, it is impossible to find your .babelrc and therefore your presets won't be applied. 但是,由于您的node目录是www的同级目录,因此您的源代码就位于该.babelrc ,因此找不到.babelrc ,因此不会应用您的预设。

You can configure options on babel-loader , which would be used regardless of the directory. 您可以babel-loader配置选项 ,无论使用什么目录,都可以使用这些选项 Unfortunately you'll run into an issue with the module resolution, which by default is the same as the Node module resolution . 不幸的是,您会遇到模块分辨率问题,默认情况下该模块Node模块分辨率相同。 When a module is imported it will be searched for in the node_modules directory and if it wasn't found there, it will look in the parent directory (ie ../node_modules ) and so on. 导入模块后,将在node_modules目录中搜索该node_modules ,如果在该目录中找不到该模块,则它将在父目录(即../node_modules )中../node_modules ,依此类推。 This is the same behaviour that Babel uses, and that's very common for tools in Node. 这与Babel使用的行为相同,并且在Node中的工具中非常常见。

The presets can be imported in the config, so they aren't being resolved from the file that is being transpiled. 可以将预设导入配置中,因此不会从正在编译的文件中解析这些预设。

{
  test: /\.(js|jsx)$/,
  exclude: /node_modules/,
  loader: 'babel-loader',
  options: {
    presets: [
      // Need to require them, so they are resolved from this config,
      // otherwise they are resolved from the directory of the file that
      // is being transpiled.
      require('babel-preset-env'),
      require('babel-preset-react')
    ]
  }
}

In addition to that you'll face the problem of resolving any module you installed with npm, because they are again in a sibling directory and won't be found. 除此之外,您还将面临解决使用npm安装的任何模块的问题,因为它们再次位于同级目录中,并且找不到。 Webpack allows you to work around that with resolve.module . 的WebPack允许您解决与resolve.module

resolve: {
  modules: [
    // Also look for modules next to the webpack config, because dependencies
    // like `react` are installed here, not where the components are.
    path.resolve(__dirname, 'node_modules'),
    'node_modules'
  ],
}

Even though that works, I strongly advise against this structure. 即使可行,我还是强烈建议您不要采用这种结构。 After all it's a workaround within webpack and if you want to add any other tool you will very likely run into issues. 毕竟,这是webpack中的一种解决方法,如果您想添加任何其他工具,则很可能会遇到问题。

The most important part is that the node modules should be in the root of your project and anything that want to use them will be in subdirectories. 最重要的部分是节点模块应位于项目的根目录中,而要使用它们的任何内容都将位于子目录中。 Something like this: 像这样:

.
├─ .babelrc
├─ manage.py
├─ package.json
├─ webpack.config.js
└─ www
   ├─ dist
   │  └─ bundle.js
   └─ templates
      ├─ home.html
      └─ react
         ├─ components
         └─ containers
            └─ Home.js

With that you don't need to work around anything and you can be sure that any module installed from npm will work. 这样一来,您无需进行任何处理,就可以确保从npm安装的任何模块都可以使用。 Additionally, you can run everything from the root of your project, whether it's installing an npm package, running webpack or running your python build. 此外,无论项目是安装npm软件包,运行webpack还是运行python构建,您都可以从项目的根目录运行所有内容。

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

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